Ошибка: ожидаемые спецификаторы объявления или "..." перед строковой константой

После компиляции моей программы Dice Roll я получил эту ошибку. Что не так с кодом?

Также до того, как я использовал get () вместо команды scanf(), но из-за этого я получил эту ошибку - передача аргумента 1 из 'gets' делает указатель из целого числа без приведения, поэтому я удалил команду gets() и использовал scanf и тогда не было ошибки относительно scanf().

В чем причина получения этих двух ошибок?


Итак, согласно ответу я узнал, как я должен был использовать команду gets() и почему я не должен использовать ее вместо этого, должен использовать scanf(). Итак, я внес изменения. Хотя я столкнулся с двумя новыми ошибками, на этот раз это связано с командой delay(), которую я использовал.

Ошибки: неопределенная ссылка на задержку | ошибка: ld вернул 1 состояние выхода |


Итак, я решил свои последние ошибки, используя команду Sleep() из библиотеки windows.h вместо команды Delay(). Программы были скомпилированы. Но все же есть ошибка во время выполнения в программе, она работает хорошо до получения roll1, но затем просто печатает следующие два оператора и завершает программы, не принимая входные данные для предположения.

Он пропускает весь код после printf("Will it be Higher/Lower or the same? (press H/L/S)\n"); и напрямую завершает программу.


Итак, я решил выше проблему, добавив пробел перед "%c" в scanf(" %c", &nextGuess); заявление. (Мелочи xD) Теперь единственная проблема в том, что мой toupper() Команда не работает.

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


int main()
{
    int i, roll1=0, roll2=0, NumberOfRolls, RandomNUM1[50], RandomNUM2[50];
    char nextGuess;

    puts("Welcome to the Dice Roll Game");
    puts("How many times do you want to roll a dice?");
    scanf("%d", &NumberOfRolls);

    for( i=1; i<=NumberOfRolls; i++ ) {
        RandomNUM1[i] = ( rand()%6 ) + 1;
        roll1 += RandomNUM1[i];
    }

    printf("\nYou Got %d in your first roll!\n", roll1);
    Sleep(3000);
    printf("\nLet's see if you can guess the value of next roll.\n");
    printf("Will it be Higher/Lower or the same? (press H/L/S)\n");
    scanf(" %c", &nextGuess);
    toupper(nextGuess);

        for( i=1; i<=NumberOfRolls; i++ ) {
        RandomNUM2[i] = ( rand()%6 ) + 1;
        roll2 += RandomNUM2[i];
    }

    if(nextGuess=='H'){
        if(roll1<roll2){
            printf("You are such a player, you guessed it right! It's %d", roll2);
        }
        else if(roll1>roll2){
            printf("Uh-Oh! Bad Luck! First roll was higher, It's %d", roll2);
        }
        else if(roll1==roll2){
            printf("Uh-Oh! Bad Luck! Both the rolls are same, It's %d", roll2);
        }

    }

    if(nextGuess=='L'){
        if(roll1>roll2){
            printf("You are such a player, you guessed it right! It's %d", roll2);
        }
        else if(roll1<roll2){
            printf("Uh-Oh! Bad Luck! First roll was lower, It's %d", roll2);
        }
        else if(roll1==roll2){
            printf("Uh-Oh! Bad Luck! Both the rolls are same, It's %d", roll2);
        }

    }

    if(nextGuess=='S'){
        if(roll1==roll2){
            printf("You are such a player, you guessed it right! It's %d", roll2);
        }
        else if(roll1>roll2){
            printf("Uh-Oh! Bad Luck! First roll was higher, It's %d", roll2);
        }
        else if(roll1<roll2){
            printf("Uh-Oh! Bad Luck! Second roll is higher, It's %d", roll2);
        }

    }

        return 0;
}

2 ответа

Решение

У вас есть шальные ,

На 2-й строке вашего mainзаявляешь char nextGuess, вместо char nextGues;

Компилятор сообщает, что ожидает спецификаторов или... после , либо вы добавляете их, либо правильно завершаете строку;

И для другой проблемы, которую вы упоминаете:

передача аргумента 1 из 'gets' делает указатель из целого числа без приведения

поскольку gets аргумент должен быть char *str и ты не обеспечил это

Вы можете исправить это, например:

char tmp_NumberOfRolls[10];
gets(tmp_NumberOfRolls);  
NumberOfRolls = atoi(tmp_NumberOfRolls);

но я предпочитаю scanf решение

PS: ***//Error Line*** не комментарий (по крайней мере, не все), так как *** по-прежнему считается частью кода и приведет к ошибке. Либо переместите // немного влево или заключить эту часть с /* ... */

gets функция читает строку (до следующего символа новой строки) из stdin поэтому он запрашивает указатель на символ (char*) в область памяти, в которую можно поместить все прочитанные символы, включая символ конца строки. Ошибка, которую вы сделали, состоит в том, чтобы передать этой функции указатель на int, поэтому вы получаете не только ошибку компилятора, потому что вы пытались передать указатель int на get (для которого нет неявных преобразований), но даже если она скомпилирована, она не сработал бы так, как вы ожидали, потому что он поместил бы все символы (которые имеют размер один байт - большую часть времени) в эту область памяти, закодированную как символы. Это означает, что когда вы пытаетесь разыменовать объект с помощью указателя на int, символы "читаются так, как будто они были целыми"!

Вот пример (предположим, что 1-байтовые символы, 4-байтовые значения int и машина с прямым порядком байтов и что существует неявное приведение типа int* к char*, которое не существует и, надеюсь, никогда не будет существовать):

int num
gets(&num);

если я введу 123 в stdin указатель на область памяти num достаточно большой, чтобы содержать строку, но он будет содержать (в десятичном представлении):

0x31|0x32|0x33|0x00

Поскольку длина строки составляет 3 символа, код ASCII для "1" равен 0x31, для "2" - 0x32, а для "3" - 0x33 и заканчивается на "\0"!! Затем, когда вы пытаетесь разыменовать его, вы получаете это int (двоичное представление - предположим, что машина с прямым порядком байтов):

00000000|00110001|00110010|00110011

который не является значением int 123, а 3224115. Который не то, что вы хотели получить.

Когда вы используете scanf Функция, вы передаете этой функции строку формата, которая сообщает ей, как интерпретировать следующие переданные ей аргументы, и выполняет соответствующие преобразования между строкой, прочитанной в правильный тип, который вы указали. Это означает, что вы все равно должны обращать внимание на то, что вы говорите scanf Функция, пока вы пишете строку формата (если вы скажете ей прочитать строку и передать ей указатель на int, программа, вероятно, завершится сбоем), но она выполнит соответствующие преобразования для вас, если вы напишите строку формата правильно.

Вот почему с scanf все работает отлично (вы читаете int, и вы указали "%d" в качестве строки формата), тогда как с gets он не компилируется, чтобы избежать серьезных ошибок.

Я также хотел бы отметить некоторые моменты этого ответа:

  • Пример только для дидактических целей, и предоставленный код не работает. Тот факт, что я предполагал, что он компилируется, предназначен для дидактических целей; очевидно, код, приведенный в этом примере , не компилируется
  • Если в этом примере мы введем строку длиной более 3 символов (а это четыре, если мы включим нулевой терминатор) или тип int (char) содержит меньше (больше), чем 4 (1) байта, программа потерпит крах, потому что мы испортили другие области памяти
  • Ссылка более техническая, чем я, в технических материалах, так что вот ссылки на gets функция и scanf функция: gets, scanfASCII Table тоже полезны)
  • Вы могли бы использовать gets функционировать вместе с atoi функция для анализа строки, прочитанной из gets (используя символьный указатель на свободную область памяти, достаточно большую, чтобы содержать строку, которую довольно трудно выделить (*)) int, но scanf это лучший подход.

(*) Помните: если вы выделите область памяти, которая содержит 20 символов, пользователь введет 21 символ. Функция atoi завершается ошибкой, но хуже всего то, что у вас переполнение буфера (и это может быть проблемой высокого уровня безопасности, если ваша программа запускается с правами root).

Другие вопросы по тегам