使用scanf时获得无限运行程序

使用scanf时获得无限运行程序,c,netbeans,scanf,C,Netbeans,Scanf,当我使用下面的代码从键盘读取字符串并将其保存在结构化向量中时,我得到了一个无限运行的程序 scanf(“%s”,strk_zgr_fp->bezeichung,(int)sizeof(strk_zgr_fp->bezeichung-1)) 在到达这一行并且程序无限运行之后,什么也不会发生 我知道不建议使用scanf()。我们只在我们的C初学者课程中使用它,我希望您记住它,即目前请不要推荐除上述功能以外的其他功能 非常感谢您的帮助,提前谢谢 #include <stdio.h> ty

当我使用下面的代码从键盘读取字符串并将其保存在结构化向量中时,我得到了一个无限运行的程序

scanf(“%s”,strk_zgr_fp->bezeichung,(int)sizeof(strk_zgr_fp->bezeichung-1))

在到达这一行并且程序无限运行之后,什么也不会发生

我知道不建议使用
scanf()。我们只在我们的C初学者课程中使用它,我希望您记住它,即目前请不要推荐除上述功能以外的其他功能

非常感谢您的帮助,提前谢谢

#include <stdio.h>

typedef struct {
    int nummer;
    char bezeichnung;
    int menge;
    float preis;
} artikel;

void eingabe_artikel(artikel *strk_zgr_fp, int i_fp);
void ausgabe_artikel(artikel *strk_zgr_fp, int i_fp);

void main(void) {
    artikel artikelliste[10];
    artikel *strk_zgr;

    int anzahl;

    do {
        printf("Bitte eine #Artikel eingeben [<= 10]: ");
        scanf("%d", &anzahl);

        if(anzahl < 1 || 10 < anzahl)
            printf("\nEs wurde eine falsche #Artikel eingegeben.");
    } while(anzahl < 1 || 10 < anzahl);

    for(int i = 0; i < anzahl; i++)
        eingabe_artikel(&artikelliste[i], i);

    int i;
    for(strk_zgr = artikelliste, i = 0; strk_zgr < artikelliste + anzahl; 
        strk_zgr++, i++)
        ausgabe_artikel(strk_zgr, i);
}

void eingabe_artikel(artikel *strk_zgr_fp, int i_fp) {
    printf("\nBitte den %d. Artikel eingeben: ", ++i_fp);

    printf("\nNummer: ");
    scanf("%d", &strk_zgr_fp->nummer);

    printf("Bezeichnung: );
    scanf("%s", strk_zgr_fp, (int)sizeof(strk_zgr_fp->bezeichnung - 1));     /* <-- */

    printf("Menge: ");
    scanf("%d", &strk_zgr_fp->menge);

    float preis;
    printf("Preis: );
    scanf("%f", &preis);
    strk_zgr_fp->preis = preis;
}

void ausgabe_artikel(artikel *strk_zgr_fp, int i_fp) {
    printf("\n%d. Artikel: ", ++i_fp);

    printf("\nNummer:\t%d", strk_zgr_fp->nummer);
    printf("\nBezeichnung:\t%s", strk_zgr_fp->bezeichnung);
    printf("\nMenge:\t%d", strk_zgr_fp->menge);
    printf("\nPreis:\t%.2f EUR\n", strk_zgr_fp->preis);    
}
#包括
类型定义结构{
国际货币基金组织;
半焦;
内蒙格;
浮标;
}阿蒂克尔;
无效艾因加贝(artikel*strk_zgr_fp,int i_fp);
无效的ausgabe_artikel(artikel*strk_zgr_fp,int i_fp);
真空总管(真空){
artikel artikelliste[10];
artikel*strk_zgr;
国际安扎尔;
做{
printf(“bite eine#Artikel eingeben[bezeichung-1]);/*menge);
浮标;
printf(“Preis:);
scanf(“%f”、&preis);
strk_zgr_fp->preis=preis;
}
无效ausgabe_artikel(artikel*strk_zgr_fp,int i_fp){
printf(“\n%d.Artikel:”,+i_fp);
printf(“\n摘要:\t%d”,strk\u zgr\u fp->nummer);
printf(“\nBezeichnung:\t%s”,strk_zgr_fp->bezeichnung);
printf(“\n名称:\t%d”,strk\u zgr\u fp->menge);
printf(“\n价格:\t%.2f欧元”,strk\u zgr\u fp->preis);
}


代码中存在许多问题。请至少修复printf()调用中缺少的结尾引号

现在谈谈牛肉:

1) 您的结构错误。“Bezeichnung”定义为单个字符,而不是字符串

typedef struct {
   int nummer;
   char bezeichnung[100];
   int menge;
   float preis;
} artikel;
2) 您不能像以前那样使用scanf()。如果要限制输入长度(这一直是个好主意),需要将最大长度传递到格式字符串中。 您需要使用scanf()吗?因为从现在开始它会变得很混乱。。。。 由于您的最大输入长度可能是可变的或可能会发生更改(请参见1.),因此您需要为scanf构建格式字符串。如下所示:

char format_str[15];
format_str[0] = '%';
//Dont use itoa(), it is not C standard.
sprintf(&format_str[1], "%d", (int)sizeof(strk_zgr_fp->bezeichnung) - 1);
strcat(format_str, "s");
scanf(format_str, strk_zgr_fp->bezeichnung);     
希望这能让你走

PS:您需要为strcat()包含string.h

我试过了,它对我来说很好。不确定这个sprintf()函数。你能解释一下我为什么要使用它吗?到目前为止,我使用了以下代码:char format_str[20];format_str[0]='%';strcat(format_str,“s”);printf(“bezeichung:”;scanf(format_str,strk_zgr_fp->bezeichung)

虽然这样做有效,但您没有限制用户输入的长度。这就是为什么我建议使用sprintf()创建(sub)包含用户输入的最大允许长度的字符串,具体取决于在结构中定义的“bezeichnung”的大小。假设“bezeichnung”限制为100个字符,则您希望将输入限制为99(+1表示零终止),因此您希望使用如下scanf格式字符串:“%99s”

chux为我的三行代码提供了一个更加紧凑的版本,但我认为,在开始时,您将更容易一块一块地组装这样的格式字符串,同时学习如何a)更改字符串中的单个字符,如何以基本方式使用sprintf(),以及如何将字符串与strcat()连接起来

还有一个例子是我做的,课程负责人提供了这样一个scanf()函数来读取字符串:scanf(“%s”&(strk_zgr_fp->bezeichung));我认为在读取字符串时不使用地址运算符。唯一的区别是现在使用了地址运算符,并且元素放在括号中

现在,我认为这是一个不好的练习。它是有效的,但是是多余的。考虑这个小代码片段:

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

struct test{
    int i;
    char a_str[10];
};

int main()
{
    struct test a_test;
    printf("Normal array adress taking: %p\n", a_test.a_str);
    printf("Using '&' to take adress of array: %p\n", &(a_test.a_str));
    return 0;
}
#包括
#包括
结构测试{
int i;
chara_str[10];
};
int main()
{
结构测试a_测试;
printf(“正常数组地址获取:%p\n”,a_test.a_str);
printf(“使用“&”获取数组地址:%p\n”,&(a_test.a_str));
返回0;
}

希望有帮助。

你不能扫描到结构中。你必须扫描到结构成员中。你真的应该检查scanf(以及
中大多数原型函数)的返回值:
if(scanf(…)!=预期的_分配)/*error*/;
你不是在检查
scanf()
确实有效。我知道您仍在学习,所以我只想确保您了解这里的另一个重要教训:您遇到的问题正是为什么经常建议避免使用
scanf
scanf
这是一个定义不好的函数。它工作不好,很难使用co正确地说,用它做更复杂的事情即使不是不可能,也是很困难的。有经验的C程序员根本不使用它;它只被初学者使用过。但由于它太难使用,初学者总是会遇到问题。使用
scanf(“%d”,&anzahl)读取整数的循环有一个大问题;
是当您输入的内容不是以可选空格、可选+/-符号和数字开头时发生的情况。在这种情况下,
scanf
将返回0,输入流将保留在非数字字符的位置。因此,当您再次循环时,该非数字字符仍然存在它将以完全相同的方式失败。除了字符格式[15];…strcat(format_str,“s”);
-->;?使用1
sprintf()
,您在3行代码中的好解决方案可以更紧凑地完成。我建议使用更大的缓冲区大小(1代表%、20代表最大为2^64的所有大小,1代表s、1代表\0)因为15似乎不清楚它的起源。@chux好的,我知道你在做什么。当我试图为明显的新手编写代码时,我试图以一种简单易懂的方式编写它