为什么我的C程序无法打印出字符串?

时间:2019-11-19 14:08:13

标签: c stack malloc

我正在制作一个程序,以打印出用户键入的内容,并且需要使用read_line()方法(用于家庭作业)完成操作,所以我不能做太多更改。

我不明白为什么它没有打印出用户输入的内容。

#include <stdlib.h>

char *read_line(char *buf, size_t sz) {
  char tempBuf[sz];
  char c;
  int pos = 0;

  printf("> ");

  while(1) {
    c = getchar();
    if (tempBuf[pos] == EOF || tempBuf[pos] == '\n') {
      buf = tempBuf;
      return buf;
    } else {
      tempBuf[pos] = c;
    }
    pos++;
  }
}

int main(int argc, char **argv) {
  char *buf;
  char *input = read_line(buf, 128);

  printf("Here: %s", input);
}

我是C语言的新手,我感到非常困惑,所以请以简单的方式解释所有内容。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:2)

char *buf;
char *input = read_line(buf, 128);

您的第一行将创建一个名为buf的指针变量,但不会为其分配任何特定值。您的第二行将buf的值传递给read_line,但是您从未为其分配任何特定值。因此,您将垃圾传递给read_line,并告诉它使用该垃圾作为缓冲区。

您可能想要char buf[128];而不是char *buf;,但这很难说。

另外,请参见我对您的read_line函数被破坏的评论,表明该函数的编写者不理解如何使用getchar

答案 1 :(得分:2)

程序中有很多错误。

对于初学者,您要向函数传递未初始化的指针

script{
def COMMITTER_EMAIL = bat (
                script: "git --no-pager show -s --format=%%ae",
                  returnStdout: true
              ).split('\r\n')[2].trim()

    echo "The last commit was written by ${COMMITTER_EMAIL}"
}

实际上没有意义传递函数中未使用的指针值。

在函数中,变量c应该声明为int类型。

char *buf;
char *input = read_line(buf, 128);

否则,如果char类型表现为unsigned char类型(取决于编译器选项),则将其与int c; 进行比较将始终得出false。

在函数中,数组tempBuf未初始化。所以这个if语句

EOF

调用未定义的行为。

在抖动范围内,您必须检查if (tempBuf[pos] == EOF || tempBuf[pos] == '\n') { 的值是否小于pos的值。

该函数返回一个指向本地数组的指针,该数组使返回的指针无效。

sz

此外,数组甚至不包含字符串,因为结尾的零未附加到数组中。

该函数应动态分配内存,并返回指向包含零终止字符串的已分配内存的指针。

下面有一个演示程序,显示了如何编写函数。

  buf = tempBuf;
  return buf;

程序输出看起来像

#include <stdio.h>
#include <stdlib.h>

char * read_line( size_t n ) 
{
    char *s = malloc( n );

    if ( s != NULL )
    {
        int c;

        printf( "> " );

        size_t i = 0;

        for ( ; i + 1 < n && ( c = getchar() ) != EOF && c != '\n'; i++ )
        {
            s[i] = c;
        }

        s[i] = '\0';
    }

    return s;
}

int main(void) 
{
    size_t n = 128;

    char *input = read_line( n );

    if ( input != NULL ) printf( "Here: %s\n", input );

    free( input );

    return 0;
}

答案 2 :(得分:0)

read_line的当前实现存在很大缺陷,原因很简单,因为它返回一个本地声明的缓冲区(该缓冲区在函数末尾被删除)。结果,您的指针指向了垃圾值(这很危险,我再说一遍,因为它会导致您的程序崩溃或变得更糟[即使在不使用内存的情况下也要继续运行))。

应该要做的是在堆上动态创建缓冲区(这样可以安全地返回它-但必须手动将其删除)。

因此,您的函数(以及代码的其余部分)应更改为以下内容:

#include <stdlib.h>

char *read_line(size_t sz) {
  // create a new buffer on the heap - so it can easily be returned (note this will have to be deleted after use using free()).
  char *tempBuf = malloc(sz);
  int c;
  int pos = 0;

  // set all elements of tempBuf to nulls
  memset(arr, 0, sz); 

  printf("> ");

  while(1) {
    c = getchar();
    if (tempBuf[pos] == EOF || tempBuf[pos] == '\n') {
      return tempBuf;
    } else {
      tempBuf[pos] = (char) c;
    }
    pos++;
  }
}

int main(int argc, char **argv) {
  char *input = read_line(128);    
  printf("Here: %s", input);

  // free the memory since we are now done with it.
  free(input);
}

您可以了解有关堆here的更多信息。