用C语言从输入文件逐字符读取字符?

用C语言从输入文件逐字符读取字符?,c,strcat,C,Strcat,我试图读取一个文件,然后读取每个字符,直到我到达一个新行,并在该行上做一些工作。以下是我迄今为止所做的工作: char line[] = ""; char *charcter = ""; //If i do this here it works fine, but below it's not working at all charcter = "asssss"; strcat(line,charcter); //Read file inputFile = fop

我试图读取一个文件,然后读取每个字符,直到我到达一个新行,并在该行上做一些工作。以下是我迄今为止所做的工作:

  char line[] = "";
  char *charcter = "";

  //If i do this here it works fine, but below it's not working at all
  charcter = "asssss";
  strcat(line,charcter);

  //Read file
  inputFile = fopen(fileName,"r");
  if (inputFile) 
  {
    while ((charcter = (char)getc(inputFile)) != EOF)
           strcat(line,charcter); //This piece code keeps crashing my program on run

    fclose(inputFile);
  }
我是一名C#开发人员,我真的很沮丧,我无法理解这件事,请帮助我

编辑:

我修改了工件线,并将内存分配给它,如下所示:

char *line = (char*)malloc( 400 *sizeof(char));
现在while循环中的strcat工作,但在获取所有值后崩溃(输入比分配的内存小得多),如果我将相同的strcat语句放入if语句中,它将获取第一个字母,然后崩溃


那么这里的问题是什么呢?

您试图修改堆栈上数组中的字符串。您将
行[]
分配为
(即一个字节,即
null
字符),然后尝试使用
strcat
在内存上涂鸦(这将修改其第一个参数指向的内存)

当您将字符串放入源代码的文本中并将其分配给函数中的数组变量时,该函数的调用框架中的堆栈上会分配大量内存。如果您在它之后访问内存,那么您将在堆栈的其他位上涂鸦,这不仅可以修改数据,还可以修改程序的行为

这就像在C#中创建一个固定数组,然后尝试附加到它。该语言不允许您这样做,因为这将涉及在数组结束后写入任何其他内存。C将允许您尝试,但随后崩溃,因为您正在涂鸦您不拥有的内存,或者更糟糕的是,让您这样做,然后在未知状态下继续运行。谁知道从
行的地址沿着几个字节还发现了什么?你没有

有关更多信息,请参见此问题:

一旦你有一个指向内存地址的指针,C只知道它是一个指针。它不知道它指向什么类型的内存(静态常量、堆栈、堆),所以它会让您犯这个错误。当您确实犯了错误时,操作系统可能会通过提出分段错误来说“实际上不,这是不允许的”,或者如果这是一个更微妙的错误,则可能不会

您应该使用
malloc
分配一个足够容纳文件的大缓冲区(危险),或者每次重新分配缓冲区以扩展它


编辑我意识到
char[]
而不是
char*
,所以编辑了我的答案

您试图修改堆栈上数组中的字符串。您将
行[]
分配为
(即一个字节,即
null
字符),然后尝试使用
strcat
在内存上涂鸦(这将修改其第一个参数指向的内存)

当您将字符串放入源代码的文本中并将其分配给函数中的数组变量时,该函数的调用框架中的堆栈上会分配大量内存。如果您在它之后访问内存,那么您将在堆栈的其他位上涂鸦,这不仅可以修改数据,还可以修改程序的行为

这就像在C#中创建一个固定数组,然后尝试附加到它。该语言不允许您这样做,因为这将涉及在数组结束后写入任何其他内存。C将允许您尝试,但随后崩溃,因为您正在涂鸦您不拥有的内存,或者更糟糕的是,让您这样做,然后在未知状态下继续运行。谁知道从
行的地址沿着几个字节还发现了什么?你没有

有关更多信息,请参见此问题:

一旦你有一个指向内存地址的指针,C只知道它是一个指针。它不知道它指向什么类型的内存(静态常量、堆栈、堆),所以它会让您犯这个错误。当您确实犯了错误时,操作系统可能会通过提出分段错误来说“实际上不,这是不允许的”,或者如果这是一个更微妙的错误,则可能不会

您应该使用
malloc
分配一个足够容纳文件的大缓冲区(危险),或者每次重新分配缓冲区以扩展它

编辑我意识到
char[]
而不是
char*
,所以编辑了我的答案

  • 您不能
    strcat()
    字符-您需要字符串
  • 字符变量的类型应为
    int
    (检查原型以了解
    getc()
  • 如果您仍然想按字符进行字符转换,请考虑按索引将其添加到字符串中(并且在结尾处终止NUL)。
      • 您不能
        strcat()
        字符-您需要字符串
      • 字符变量的类型应为
        int
        (检查原型以了解
        getc()
      • 如果您仍然想按字符进行字符转换,请考虑按索引将其添加到字符串中(并且在结尾处终止NUL)。
      请不要将其称为
      NULL
      字符。由于
      NULL
      是一个地址常量,而不是令牌。而且
      也不会“分配某些东西”,好吧。
      肯定是在编译时在程序文本中分配一个空字符串吗?也许我们彼此误解了,我说的是空字符(
      '\0'
      )而不是
      null
      内存地址。
      0x0
      '\0'
      之间的区别在于,第一个是指向一个空的单字节空字符串的指针,第二个是零值。但是这个jsut不是被称为“零令牌”或“零终止符”吗?那你为什么叫它空字符?“它不知道它指向什么类型的内存”顺便说一句,这也是不正确的,因为C提供了别名规则,其中对齐内存块的类型非常重要;)我称它为空字符,因为它在字符集中被称为空字符。请看这里:是的,C知道指针的类型,但不知道它是指向常量程序文本还是指向t