【问题标题】:Scanf keeps waiting for input after a string with spaces is entered?输入带空格的字符串后,scanf一直在等待输入?
【发布时间】:2018-11-25 19:47:37
【问题描述】:

这是捕获字符串的函数:

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;
}

问题在于上面的选项五在 switch 案例中:它仅在捕获的字符串没有任何空格时执行。例如,如果您输入“Hello world”。案例5永远不会执行并且scanf

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

只会呆在那里等待输入。这只会发生,我重复一遍,如果捕获的字符串有空格 AND 您在 switch case 中选择选项 5

【问题讨论】:

  • 不知函数sort是不是有错误或者死循环...
  • @GenoChen 在原帖中添加了排序功能。
  • @DavidSchwartz 因为如果我不这样做,Visual Basic 会给我错误“分段错误(核心转储)”:(
  • @UrielGuzmán 如果您进行了您不理解的更改来修复错误,您应该在寻求帮助之前将其删除并发布您认为应该可以工作的代码。否则,你得到的帮助可能会让你回到原来的位置,更糟糕的是,它是关于你不理解也不会编写的代码的建议。 (很可能我给你的答案只是让你回到你破坏代码之前试图修复它之前的状态。抱歉。)
  • @DavidSchwartz 谢谢。我在原始帖子中修复了数组问题。但问题仍然存在。

标签: string input scanf spaces


【解决方案1】:
            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");
}

糟糕,capture 写入了 string 过去的地址,但这已经超出了您分配的数组的末尾。在您分配的范围之外写入内存可能会践踏其他变量并导致不可预测的结果。在您修复越界写入之前,您真的无法调试程序中的任何其他内容。您可以使用valgrind 或类似工具来帮助检测此类错误。

【讨论】:

  • 看来我错误地将数组传递给函数。在原始帖子中修复了该问题。但是,问题仍然存在。 PS:程序在等待输入时崩溃。它看起来也像一个无限循环问题。
  • 你触及了问题的核心。我在我的设备上尝试了 gdb,发现在 return 0;main 之后有一个堆栈粉碎。但我不知道为什么会出现在这个声明中。
  • 哦,原来问题的代码,连stringstring_copy都被改写成一些意想不到的值了……
【解决方案2】:

我试图理解你的逻辑,但那里似乎有问题:

为什么要将 string[50] 传递给每个函数?我假设您想在每个函数中使用相同的字符串变量,因此,您需要检查两点:

  1. 您应该要求用户在 switch() 语句之前输入字符串值 - 例如,在 switch() 行之前的行中调用 capture()。否则,用户可以在进入“捕获”功能之前输入其他菜单选项,并且在这种情况下,字符串将不存在,导致分段错误 - 如果我没记错的话。 (你试过吗?比如选择选项3,在选择选项1之前?肯定不行)

  2. 要通过参数传递“string”变量,请使用“string”,而不是“string[50]”。 在声明之后(其中“50”是字符串的大小),表达式“string[50]”表示字符串的第 50 个值,正如大卫的回答所指出的那样,它甚至不存在。

【讨论】:

  • 是的。大卫在这件事上是对的。几分钟前已经更正了原帖中的字符串参数。 (它现在传递的是字符串而不是 &string[50])。不过,在我纠正之后,分割错误就消失了。但是问题的原始问题仍然存在。我也只是按照您在第 1 点中所说的做了。尽管它没有解决问题。我会保持这种状态,因为正如您所说,最好先捕获字符串。
  • 你检查过第 1 期吗?
  • 我也看不懂 "scanf(" %[^\n]s", string);"在函数捕获()中。您是否尝试过仅使用 "scanf("%50c", string)" ? %s 读取任意数量的非空白字符,在找到的第一个空白字符处停止。终止的空字符会自动添加到存储序列的末尾。来自:cplusplus.com/reference/cstdio/scanf你看看那里...
  • 对不起,我打错了。我的意思是我更正了问题 1(和问题 2)。 scanf(" %[^\n]s", 字符串);用于接受带空格的字符串,在遇到换行符之前停止。我一开始留了一个空格,因为选项菜单的换行符弄乱了scanf。尝试了 fgets() 甚至使用 getchar() 来吃换行符,但它们似乎与原始问题无关。
  • 我明白了。我现在需要离开,但如果问题仍然存在,我可以稍后尝试帮助您。我在之前的评论中为您推荐了一个链接,希望对您有所帮助.. ':)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-30
  • 1970-01-01
  • 2016-02-23
  • 1970-01-01
相关资源
最近更新 更多