我正在学习C,并做一些挑战,比如在exercism.io和各种数据结构和算法站点上发现的挑战。
我有一种感觉,虽然这是可行的,但对我来说,它是可以改进的,而且可能不是专业的C程序员解决它的方法。
有兴趣的,如果这将通过一个专业的环境的代码审查,如果没有,为什么不。
问题网址:将短语转换为首字母缩略词
把一个短语转换成它的缩写词。技术人员喜欢他们的TLA (三个字母缩写)!通过编写一个程序来帮助生成一些行话,该程序将一个长名称(如)转换为其缩写(PNG)。
acronym.h
#ifndef ACRONYM_H
#define ACRONYM_H
char *abbreviate(const char *phrase);
#endif#include "acronym.h"
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
char *abbreviate(const char *phrase) {
// Return NULL for NULL or empty phrase
if (phrase == NULL || strlen(phrase) == 0) {
return NULL;
}
size_t phrase_length = strlen(phrase) - 1;
size_t acronym_index = 0;
size_t phrase_index = 0;
// The acronym will not be longer than the phrase length.
char *acronym = malloc(phrase_length * sizeof(char));
// The first letter of the phrase is the first initial in the acronym.
acronym[acronym_index] = toupper(phrase[phrase_index]);
acronym_index++;
phrase_index++;
while (phrase[phrase_index] != '\0') {
// At the end of the string, add a null terminator.
if (phrase_index == phrase_length) {
acronym[acronym_index] = '\0';
acronym_index++;
phrase_index++;
break;
}
char letter = phrase[phrase_index];
char next_letter = phrase[phrase_index + 1];
// If letter is not an apostrophe or alpha character, but the next one is,
// found a word boundary and the next charcter is part of the acronym.
if (letter != '\'' && !isalpha(letter) && isalpha(next_letter)) {
acronym[acronym_index] = toupper(next_letter);
acronym_index++;
phrase_index++;
}
phrase_index++;
}
return acronym;
}发布于 2021-10-09 18:25:54
我会告诉你我会先写些什么:
char *abbreviate(const char *phrase) {
assert(phrase);
char *acronym = malloc(strlen(phrase) / 2 + 1);
if (!acronym) {
return NULL;
}
char previous = ' ';
size_t len = 0;
for (size_t i = 0; phrase[i]; i++) {
char current = phrase[i];
if (previous != '\'' && !isalpha(previous) && isalpha(current)) {
acronym[len++] = toupper(current);
}
previous = current;
}
acronym[len++] = '\0';
return realloc(acronym, len);
}首先,我要求用非空指针调用函数,因为传递空指针可能是调用方的编程错误。我使用一个assert()调用来检查它,它可以在发布版本中编译出来。
然后有各种分配内存的方法;您可以从一个小缓冲区开始,并在必要时扩展它,或者以缩略词的最大大小开始,即只有原始短语的一半大小。不要忘记检查malloc()是否成功,并以某种方式处理它返回的NULL。
与其将当前字符与下一个字符进行比较,不如将当前字符与前一个字符进行比较。这是我的代码短的主要原因;我不需要检查我们是否已经在最后一个字符上了,通过仔细初始化current,phrase中的第一个alpha字符将正确地成为输出中的第一个字符。注意,您的代码会很高兴地将短语的第一个字符复制到首字母缩写中,即使它不应该这样做。
最后,在确保首字母缩略词以NUL字节正确结束后,我将分配的内存缩小到缩略词所需的最小值;这样就避免了浪费内存。(从技术上讲,您应该检查realloc()的返回值,因为它可能返回NULL,但我在这里滥用了多年的编程经验,假设如果您收缩而不是增长,这种情况永远不会发生。)
注意,如果输入中没有alpha字符,则此版本可能返回空字符串。您可能想要也可能不想要这种行为。其结果是,该函数将始终返回一个有效的字符串,除非内存分配失败。调用者仍然可以轻松地检查它是否为空。如果您希望它返回NULL,我建议在最后这样做:
if (len) {
acronym[len++] = '\0';
return realloc(acronym, len);
} else {
free(acronym);
return NULL;
}我会为您的测试套件添加更多的角用例,比如以空格开头的输入,以及只由非alpha字符组成的输入。
发布于 2021-10-09 18:44:18
我会创建类似于下面的内容,它允许更好的错误处理,并在堆栈上声明输出缓冲区。
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
enum AbbreviationErrors
{
phraseIsNull = 1,
bufferTooSmall = 2,
noLettersFound = 3
};
int abbreviate(const char* phrase, char* buf, const size_t bufSize)
{
if (phrase == NULL)
return phraseIsNull;
int inAlpha = 0;
char prevChar = 0;
char* dst = buf;
for (const char* ptr = phrase; *ptr; ptr++)
{
if (isalpha(*ptr))
{
if (inAlpha == 0 && prevChar != '\'')
{
if (dst - buf >= bufSize)
return bufferTooSmall;
*dst++ = toupper(*ptr);
inAlpha = 1;
}
}
else
{
inAlpha = 0;
}
prevChar = *ptr;
}
if (dst == buf)
return noLettersFound;
if (dst - buf >= bufSize)
return bufferTooSmall;
*dst = '\0';
return 0;
}
int main()
{
char test[] = "Hailey's Comet";
static const size_t bufLen = 80;
char buf[bufLen];
int result = abbreviate(test, buf, bufLen);
if (result == 0)
printf("abbreviation = '%s'\n", buf);
}发布于 2021-10-12 18:07:49
对不起,不能添加评论,所以会尝试将其作为回答。
我已经测试了你在Git中的代码。当美国通过时,它返回U。我知道你不能将这种论点与任何东西进行比较,但任务要求是否不明确呢?正如我们所知(维基百科):
短语可以由一个单词或一个完整的句子组成。
也许在这种情况下,只有一个单词,所有的字母都是大写字母,让它保持原样?
https://codereview.stackexchange.com/questions/268821
复制相似问题