Scanf продолжает ждать ввода после ввода строки с пробелами? - PullRequest
0 голосов
/ 25 ноября 2018

Это функция, которая захватывает строку:

void capture(char string[]) {
    printf("_____________________________________________________________\n\n");
    printf("Ingrese una cadena: ");
    scanf(" %[^\n]s", string);
    printf("Cadena capturada: %s\n", string);
    printf("_____________________________________________________________\n\n");
}

Это функция, которая вызывается в основной функции:

    void sort(char string[]) {  
int opt, i, j, temp = 0;
char string_copy[50];
strcpy(string_copy, string);
for (i = 0; string_copy[i] != '\0'; i++) 
    for (i = 0; string_copy[i] != '\0'; i++) {
        for (j = i + 1; string_copy[j] != '\0'; j++) {
            if (string_copy[i] > string_copy[j]) {
                temp = string_copy[i];
                string_copy[i] = string_copy[j];
                string_copy[j] = temp;
            }
            }
            }

printf("_____________________________________________________________\n\n");
printf("Ordenar de modo:\n1) Ascendente\n2) Descendente\n");
printf("Seleccione una opcion: ");
fflush(stdin);
scanf(" %d", &opt);
switch(opt) {
    case 1: 
            printf("'%s' ordenado de forma ascendente: %s\n", string, string_copy);
            break;
    case 2: 
            printf("'%s' ordenado de forma descendente: ", string);
            for (i=strlen(string); i != 0; i--)
                printf("%c", string_copy[i]);
            printf("\n");
            break;
    default: printf("[ ! ] Selección incorrecta!\n"); break;
}
printf("_____________________________________________________________\n\n");
}

//Imprimir la última palabra de la cadena
void last_word(char string[50]) {
    printf("_____________________________________________________________\n\n");
    int i, count = 0;
    for (i=0; string[i] != '\0'; i++) {
        if (string[i] == ' ') {
            count = i;
        }
    }
    if (count == 0) {
        printf("Solamente hay una palabra: %s\n", string);
    } else {
        printf("La última palabra en '%s' es: ", string);
        for (i=count; string[i] != '\0'; i++) {
            printf("%c", string[i]);
        }
        printf("\n");
    }
    printf("_____________________________________________________________\n\n");
}

И этот код имеетпроблема:

int main() {
int opc = 0;
char string[50];
do {
    printf("MENU:\n");
    printf("1) Capturar cadena\n");
    printf("2) Sustituir un caracter por otro\n");
    printf("3) Buscar un caracter e imprimir el número de veces que aparece\n");
    printf("4) Buscar un caracter para eliminar de la cadena.\n");
    printf("5) Ordenar los caracteres alfabéticamente\n");
    printf("6) Imprimir la última palabra de la cadena\n");
    printf("0) Salir\n");
    printf("Seleccione una opcion: ");
    scanf("%i", &opc);
    printf("Opcion: %d", opc);
    switch(opc) {
        case 1:{
                capture(string);
                break;
        }
        case 2:{
                replace(string);
                break;
        }
        case 3:{
                num_char(string);
                break;
        }
        case 4:{
                delete(string);
                break;
        }
        case 5:{
                sort(string);
                break;
        }
        case 6:{
                last_word(string);
                break;
        }
        case 0:{
                printf("Bye\n");
                break;
        }
        default: {
                printf("[ ! ] Selección incorrecta!\n");
        }
    }
} while (opc != 0);

    return 0;
}

Проблема с опцией пять выше в случае коммутатора: он выполняется только в том случае, если в захваченной строке нет пробелов.Если вы введете «Hello world», например.Случай 5 никогда не будет выполнен, и scanf

printf("Seleccione una opcion: ");
scanf("%i", &opc);

будет просто оставаться там в ожидании ввода.Это происходит только, повторяю, если в захваченной строке есть пробелы И , в случае переключателя вы выбираете опцию пять .

Ответы [ 2 ]

0 голосов
/ 25 ноября 2018

Я попытался понять вашу логику, и, похоже, там есть проблема:

Почему вы передаете строку [50] каждой функции?Я предполагаю, что вы хотели бы использовать одну и ту же строковую переменную в каждой функции, поэтому вам нужно проверить две точки:

  1. Вы должны попросить пользователя ввести строковое значение до того, какоператор switch () - например, вызов capture () в строке перед строкой switch ().В противном случае пользователь может войти в другие пункты меню перед тем, как войти в функцию «захвата», и в этом случае строка еще не будет существовать, что приведет к ошибке сегментации - если я не ошибаюсь.(Вы пробовали это? Выбор варианта 3, например, перед выбором варианта 1? Он не должен работать)

  2. Чтобы передать переменную "string" по параметру, используйте "string",не "строка [50]".После объявления (где «50» - размер строки), выражение «string [50]» представляет 50-е значение строки, которого даже не существует, как указано в ответе Дэвида.

0 голосов
/ 25 ноября 2018
            capture(&string[50]);

Вы передаете capture адрес string[50].Но нет string[50].Таким образом, вы передаете адрес после конца string на capture.(Поскольку string содержит пятьдесят записей, а 0 - первое, 49 - последнее. string[50] нет, он находится за концом массива.

void capture(char string[50]) {
    printf("_____________________________________________________________\n\n");
    printf("Ingrese una cadena: ");
    scanf(" %[^\n]s", string);
    printf("Cadena capturada: %s\n", string);
    printf("_____________________________________________________________\n\n");
}

Ooops, capture записывает по адресу, который был передан для string, но это после конца выделенного вами массива. Запись в память за пределами выделенных вами границ может растоптать другие переменные и приводить к непредсказуемым результатам. Пока вы не исправите записи вне границ,Вы действительно не можете отлаживать что-либо еще в своей программе. Вы можете использовать valgrind или подобный инструмент, чтобы помочь обнаружить такие ошибки.

...