5

因此,假设我有一个 char,我想在一行代码中将它 strcat() 转换为 char 数组。对于[一个不实用的]示例:

strcat("ljsdflusdfg",getchar());

或者我想做相反的事情,无论数据类型如何,连接或类型转换字符串的适当函数是什么?或者也许我缺少一些语法......

这是一个例子。它编译得很好但崩溃了。

char* input(){
 char* inp="";
 while(1){
  char c=getchar();
  if(c){
   if(c=='\n'||c==EOF){
    break;
   }else{
    strcat(inp,(char*)c);
   }
  }
 }
 return inp;
}
4

8 回答 8

3

strcat将其参数视为指向以 nul 结尾的字符串的指针。将 achar转换为 achar *是危险的,我无法想象它没有任何用处的理由(并不是暗示你尝试它是愚蠢的 - 每个人在学习时都会犯愚蠢的错误。这就是我们在这里的原因。)

原因是它会将单个 bytechar以及sizeof(char*) - sizeof(char)围绕 that 的额外(通常 3 个)字节解释char为指针,该指针将指向...任何地方。您无法知道它指向的位置,因为其中 3 个字节超出了您的控制范围,因此无法知道它是否指向有效数据。

您可以将此作为第二种方法:

strcat(inp, &c);

这一次,你会做得更好,因为&c它是一个类型的表达式char *并且不需要强制转换。但同样,strcat假设它的参数是一个以 nul 结尾的字符串,并且由于您无法保证char数据后有一个 nul 字节,因此这是行不通的。

最好的方法是这样的:

size_t len = strlen(inp); // this may already be calculated somewhere else
...
inp[len++] = c; // add c as the last character, and adjust our len
inp[len] = '\0'; // add a new nul terminator to our string

更新:

其实,我撒了谎。最好的方法是使用标准库函数fgets,它似乎或多或少地在做你想做的事情。老实说我忘记了,但如果这是一个家庭作业,你的教授可能不希望你使用fgets,这样你就可以学习如何手动完成。但是,如果这不是家庭作业,fgets则完全符合您的要求。(实际上,第三种方法正在重新实现fgetsfgets类似功能的路上。)

我还将对您的input功能添加一些其他评论:

  1. char* inp = "";将指向只读数据。C 标准中的一个缺陷(为了向后兼容)允许将字符串文字分配给char*类型,而不是const char *它应该的类型(恕我直言)。

    有几种方法可以解决这个问题,但最好的方法是动态分配。使用该malloc函数来保留一些数据,跟踪您在函数中使用了多少,realloc如果您最终需要更多空间来存储它,请使用该函数。如果您需要这方面的帮助,我相信您会回到这里(希望不会太早)提出另一个问题。:)
  2. getchar()返回 a int,因为EOF被定义为超出 a 的正常范围char。为了区分任何charand EOF,最好制作c一个int. 否则,一个完全有效的字符可能会发出信号EOF。但是,当您将其添加到字符串时,请务必将其转换c为 a 。char
于 2011-01-14T03:09:35.083 回答
2
strcat(inp,(char*)c);

那是试图将内存的内容连接到“c”(作为内存位置)所在的位置,直到找到零为止。

更好的方法是创建一个您认为合理的最大大小的空字符串,用零填充它,然后在当前最后一个位置插入“c”

于 2011-01-14T03:06:05.270 回答
2

如果您希望将单个连接char到字符串上,您可以使用strncat()并指定要连接的字符数为1. 但请注意:

  • 目标缓冲区必须有足够的空间;和
  • 在 C89 中,您必须有一个实际char对象来获取地址(因此您不能直接连接getchar().

例如:

char str[5] = "foo";
char c;
int ch;

if ((ch = getchar()) != EOF) {
    c = ch;
    strncat(str, &c, 1);
}

在 C99 中,您可以使用复合文字,并且第二个限制不适用:

char str[5] = "foo";
int ch;

if ((ch = getchar()) != EOF) {
    strncat(str, &(char){ ch }, 1);
}
于 2011-01-14T05:00:23.420 回答
1

这不起作用,因为 *inp char 指针没有任何内存支持它。当你声明它是 char *inp = ""; 时,你只给了它一个空字符串的地址。如果您给出了以下声明 char *inp = "abcdefg",那么您可以在覆盖 '\0' 并遇到麻烦之前向其写入 7 个字符。

当您输入越来越多的字符时,您将需要动态增加后备内存的大小。您还将遇到知道何时释放内存的问题,以免发生内存泄漏。

此外,您的 strcat 需要在 c 之前有 '&'。

于 2011-01-14T03:07:13.657 回答
0

首先,您将返回一个指向堆栈分配数组的指针。这是未定义的行为。其次,您正试图将字符写入未分配的内存。第三, 的类型inp不是。const char*char*

你想要这样的东西:

char* input(char *dest) {
  strcpy(dest,"");
  while(1){
  char c=getchar();
  if(c){
   if(c=='\n'||c==EOF){
    break;
   }else{
    strcat(inp,&c);
   }
  }
 }
 return dest;
}
于 2011-01-14T03:07:46.953 回答
0

您的代码崩溃是因为 strcat 的两个参数都需要以空字符结尾的字符串。

如果要连接一个 char,首先需要从它创建一个以空字符结尾的字符串。

char c[2] = {0,0};
c[0] = getchar();
strcat(inp, c);

不要使用 strcat,除非您可以保证输入字符串已为该额外字符分配空间。对你更好的 strncat 还包括第一个参数(dest)中的空间量参数。

我建议先阅读这篇文章。

于 2011-01-14T03:08:58.890 回答
0

一种简单的方法是使用 snprintf:

char newString[50+1];
snprintf(newString, sizeof(newString), "%s%c", "ljsdflusdfg", getchar());

这是一个简单的解决方案,但确实需要您提前大致知道字符串的大小。

注意:我使用 +1 来提醒自己需要为 null 终止留出空间,并且 snprintf 比 sprintf 更好,因为它提供了缓冲区的大小以防止缓冲区溢出。

于 2013-08-08T05:59:12.767 回答
-1

将 char 转换为 char 数组?
这就像说你想把一个字符转换成字符串。
你不能直接这样做。
而不是 char,将它放在一个数组 (myChar[]) 中。
之后,用你原来的 char 数组 strcat 。

于 2011-01-14T03:09:03.987 回答