使用malloc动态分配字符串

时间:2014-07-30 04:26:28

标签: c string pointers

我是C编程新手。现在我正在学习字符串和指针 作为初学者,我发现很难找到错误。我编写了一个动态分配字符串的代码,并使用函数打印字符串。代码如下所示。

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

 void fun (char *);

 int main()
 {
    int n;
    char *s = NULL;
    printf("enter the length of the string\n");
    scanf("%d",&n);
    s  = (char*)malloc(n * sizeof(char));
    printf("enter the string\n");
    fgets(s, 20, stdin);
    printf("string before  passing is %s\n",s);
    fun(s);
    return 0;
 }

 void fun( char *p)
 {
    char *d;
    d = p;
    printf("string after passing is%s\n",d);      
 }

编译时没有错误消息。但是代码并没有采用字符串 谁能帮助我找到错误。

5 个答案:

答案 0 :(得分:4)

您的代码中有五个主要错误。

  1. scanf不会&#34;消费&#34;点击 ENTER 时生成的换行符,因此您需要getchar来跟踪它以处理此意外行为。
  2. 您未查看malloc的结果。此功能可能会失败。
  3. fgets应使用n来确定要从用户处获取的最大数据量,否则您将通过溢出缓冲区来生成细分错误。
  4. 包含fgets结果的字符串以换行符结束,在典型情况下为NULL终止字符。您可以使用strtok替换带有NULL字符的尾部换行符,以避免意外行为。
  5. 您不是free使用malloc创建的内存。这会导致内存泄漏。
  6. 编辑:Matt McNabb提供了另一种方法来处理FIX1中未消耗的\n,我认为这种方法比我的方法更清晰。

    解决方案发布在下方。

    代码清单


    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    void fun (char *);
    
    int main() {
       int n;
       char *s = NULL;
       printf("enter the length of the string\n");
       scanf("%d",&n);
       (void)getchar();     // FIX1
    
       s  = (char*)malloc(n * sizeof(char));
       if (s == NULL) {     // FIX2
          printf("malloc error; aborting\n");
          return 1;
       }
       printf("enter the string\n");
       fgets(s, n, stdin);  // FIX3
       strtok(s, "\n");     // FIX4
       printf("string before  passing is %s\n",s);
       fun(s);
       free(s);             // FIX5
       return 0;
    }
    
    void fun(char *p) {
       char *d;
       d = p;
    
       printf("string after passing is %s\n",d);
    }
    

    示例运行


    enter the length of the string
    10
    enter the string
    This is a test for overflows.
    string before  passing is This is a
    string after passing is This is a
    

答案 1 :(得分:1)

scanf("%d",&n);

输入数字并按ENTER后,此scanf行所采用的数字,但新行字符仍在缓冲区中。下一个fgets行只占用新行。

解决问题的一种简单方法是:

scanf("%d",&n);
getchar();      //consume the new line

答案 2 :(得分:1)

当您编写scanf("%d",&n);时,它会从流中提取整数。它不会丢弃剩余的线。因此,如果您键入一个数字并按下Enter键,则换行符将保留在流中。

所以当你fgets时,它会读取该行的其余部分,这是空白的。

要解决此问题,您需要阅读最后一行。一种方法是:

int ch;
while ( (ch == getchar()) != '\n' && ch != EOF ) { }

然后你可以继续做:

fgets(s, n, stdin);   // n, not 20

另外,你应该检查malloc的结果,例如

 s  = malloc(n);
 if ( s == NULL )
     return 0;   // or some other error handling

自1989年以来,Castoc malloc一直是a mistake,但是你是否想要包括sizeof(char)是一个风格问题,因为sizeof(char)总是1。< / p>

要完成,您还可以检查fgets的结果,例如,如果您的输入已关闭,那么您将输出垃圾。

答案 3 :(得分:1)

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

void fun (char *);

int main()
{
        int n;
        char *s = NULL;
        char ch;

        /* Taking String length from the User */
        printf("enter the length of the string\n");
        scanf("%d",&n);

        /* Allocating Memory */
        s = (char*)malloc(n * sizeof(char));

        /* Checking for memory allocation */
        if (s == NULL)
        {
                printf("\n Error in allocating memory \n");
                exit(0);
        }

        /* Flush standard inputs */
        while ((ch = fgetc(stdin)) != EOF && ch != '\n')
        {
        }

        printf("enter the string\n");
        fgets(s, n+1, stdin);

        printf("string before  passing is %s\n",s);
        fun(s);

        /* Need to free the allocated memory */
        free(s);
        return 0;
}

void fun( char *p)
{
        char *d;
        d = p;
        printf("string after passing is %s \n",d);
}

答案 4 :(得分:0)

简而言之,fgets从缓冲区读取并且缓冲区已经满了。解决方法是在阅读

之前不要使用fgets或flush buffer
printf("enter the string\n");
fflush(stdin);
fgets(s, 20, stdin);

UPD

所以如果stdin没有定义fflush,那么就像上面提到的Matt McNabb那样冲洗它

while ((ch = getchar()) != '\n' && ch != EOF);