【问题标题】:expected expression before charchar 之前的预期表达式
【发布时间】:2021-06-06 18:18:56
【问题描述】:

我编写了这个程序,它询问用户一个名字,然后打印这个名字。详细步骤如下:

  • 询问用户名称(即句子)的字符数。它包含空格和终止符\0,然后存储它;
  • 它使用num_char地址创建一个内存块,并将第一项的地址存储在ptr中;
  • else部分中,声明了一个未知大小的数组,用于存储名称,并将其首地址分配给ptr
  • 然后为数组分配大小num_char

代码如下:

#include <stdio.h>
#include <stdlib.h>
//an attempt at a program that asks for a name, stores it in an array and then prints it

int main() {
    int num_char;
    char *ptr;

    printf("input number of characters of your name (spaces and terminator character included): ");

    scanf("%d", &num_char);

    ptr = char *malloc(num_char * sizeof(char)); //creates a block of mem to store the input name, with the same size, and then returns the adress of the beginning of the block to ptr

    if (ptr == NULL) {
        printf("allocation not possible");
    } else {
        ptr = char name[]; //ptr stores the adress of the first char in string

        char name[num_char], //declaration of an array with num_char elements

        printf("input name: ");

        scanf("%s", name);
        printf("input name was: %s", name);
    }
    return 0;
} 

但是我得到三个编译错误:

  • “'char' 之前的预期表达式”ptr = char *malloc(num_char * sizeof(char) );ptr = char name[];
  • “预期的声明说明符或字符串常量之前的'...'”printf("input name: ");

我是一名刚开始学习 C 和一般编程的大学生,因此非常感谢详细解释任何类型的错误以及如何修复它:)

【问题讨论】:

  • ptr = char *malloc(num_char * sizeof(char) ) 只需删除char *。如果您要进行强制转换,那么它需要是 (char *),但在 C 中不需要强制转换。
  • char name[num_char], -> char name[num_char];
  • ptr = char *malloc(num_char * sizeof(char)); 应该是 ptr = malloc(num_char);shouldn't cast the result of malloc,而 sizeof(char) 根据定义是 1,所以乘以 sizeof(char) 是没有意义的。
  • @chqrlie ptr = char name[];
  • 这是一个奇怪的赋值,所以你为ptr分配内存,然后你必须为ptr分配一个数组?这就是内存泄漏。

标签: arrays c pointers compiler-errors malloc


【解决方案1】:

这些是语法错误,因为:

  • ptr = char *malloc(num_char * sizeof(char)); 应该是 ptr = (char *)malloc(num_char * sizeof(char)); 或只是 ptr = malloc(num_char * sizeof(char));

  • ptr = char name[]; 毫无意义。您根本不需要更改ptr

  • char name[num_char], 是一个 C99 可变长度数组定义,但有一个尾随 ,,因此下一行应该有另一个定义,因此出现第二个错误。

您必须选择使用malloc() 从堆中分配内存或将数组定义为局部变量。

这是修改后的版本:

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

int main() {
    int num_char;
    char *ptr;

    printf("input number of characters of your name (spaces and terminator character included): ");

    if (scanf("%d", &num_char) != 1 || num_char <= 1) {
        printf("invalid input\n");
        return 1;
    }
    /* discard the rest of the input including the newline */
    int c;
    while ((c = getchar()) != EOF && c != '\n')
        continue;

    //allocate a block of memory to store the name
    ptr = malloc(num_char * sizeof(char));

    if (ptr == NULL) {
        printf("allocation not possible");
    } else {
        printf("input name: ");

        if (scanf("%[^\n]", ptr) == 1)
            printf("input name was: %s\n", name);
        else
            printf("no input was given\n");

        free(ptr);
    }
    return 0;
} 

还要注意,如果输入有更多的非白色字节,scanf() 可能会读取超过num_char 字节,因此给scanf() 提供有关数组大小的信息会更安全,但并非微不足道:

    if (ptr != NULL) {
        char format[32];
        snprintf(format, sizeof format, "%%%d[^\n]", num_char - 1);
        printf("input name: ");
        if (scanf(format, ptr) == 1) {
            printf("input name was: %s\n", name);
            // should discard the rest of the line and the newline
        } else {
            printf("no input was given\n");
        }
    }

【讨论】:

    【解决方案2】:

    正如我在 cmets 中所说,这是一组奇怪的要求,我假设是一个作业,这里或多或少是你应该使用 cmets 做的:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void clear_buffer()
    { // routine to clear standard input
        int c;
        while ((c = getchar()) != '\n' && c != EOF){}
        if (c == EOF)
        {
            exit(EXIT_FAILURE);
        }
    }
    
    int main()
    {
        int num_char;
        char *ptr;
    
        printf("input number of characters of your name (spaces and terminator character included): ");
        // less than 9 + 1 null byte characters for the name not allowed
        while (scanf("%d", &num_char) != 1 || num_char < 10)
        { 
            printf("Bad input, try again: ");
            clear_buffer();
        }
        ptr = malloc(num_char); // removed char*, you may wanted a cast, 
                                // but even that is unneeded,
                                // The size of char is always 1 byte
                                // I still don't understand why this is asked, but well...
        if (ptr == NULL)
        {
            perror("allocation not possible"); // perror prints the apropriate error
        }
        else
        {
            char name[num_char]; // declaration of an array with num_char elements
            free(ptr);           // to make ptr point to another memory location, it must be freed
            ptr = name;          // ptr now points to the first element of the name array
    
            clear_buffer();
            printf("What's the name ? ");
            // read name with spaces from standard input
            if (fgets(name, num_char, stdin))
            {                   
                name[strcspn(name, "\n")] = '\0'; // remove \n 
                printf("input name was: %s", ptr); // print name through ptr 
            }  
            else
            {
                puts("Bad input");
            }                    
           
        }
        return EXIT_SUCCESS;
    }
    

    等待模棱两可的解释...

    【讨论】:

    • while ((c = getchar()) != '\n' &amp;&amp; c != EOF){} 在所有情况下都需要,否则fgets() 将只读取输入的第一行的其余部分...并且换行符将保留待定,因为名称恰好具有num_char-1人物。文件读取意外结束时也会无限循环num_char
    • 嗯...如果fgets(name, num_char, stdin) 返回NULL,您的行为未定义,但我也已经过了就寝时间了:)
    • @chqrlie,确实,我确实打破了scanffgets 混在一起的潜规则,反正这些答案中的任何一个都太防弹了,老师会想知道这是谁干的:)
    猜你喜欢
    • 2013-10-03
    • 1970-01-01
    • 1970-01-01
    • 2014-11-30
    • 2019-10-28
    • 2016-07-26
    • 1970-01-01
    • 2021-06-15
    • 2014-09-06
    相关资源
    最近更新 更多