c-do循环执行不正确



我有一个函数readin((读取一些人的名字和他们对应的电话number,并返回已输入的名称数。字符"#"用于指示用户输入的结束。

int readin(Employee *emp)
{
int i=0,j;
do { // loop statements to be executed no matter what
printf("Enter name:n");
scanf("%s",emp->name); // stores name inside structure array
j = (strcmp(emp->name,"#") != 0); // returns 1 if name not equals to #
} while(j);{ // while name is not equals to # , execute code below and loop back 'do'
printf("Enter tel:n");
scanf("%s",emp->telno);
emp++;
i++;
}
return i;
}

预期结果应为:

Enter name:
John
Enter tel:
12345678
Enter name:
#

获得的结果:

Enter name:
John
Enter name:
#
Enter tel:

当j=1时,while循环不运行,但它循环回do部分,而不是完全退出循环。当j=0时,while循环中的代码由于某种原因而被执行。请告知。

你知道这就是在工作时做的确切方式

do{
state1;
}
while(statement);
rest of code;

如果语句为真,它将转到状态部分并再次执行,当语句出错时,它将转到代码的其余部分。

在您的情况下,while string!='#'您将始终进入do while((循环,当语句错误或j==0时,您将退出do while循环

我推荐这个:

int readin(Employee* emp)
{
int i = 0, j =0;
while (1)
{
printf("Enter name:n");
scanf("%s", &emp->name);
if((strcmp(emp->name, "#") == 0))
break;
printf("Enter tel:n");
scanf("%s", &emp->telno);
emp++;
i++;
}
return i;
}

scanf用于面向行的输入是错误的选择。读取用户输入行的推荐方法是使用fgets()或POSIXgetline()

为什么要使用fgets((

简而言之,它更健壮,它处理内部空白,允许您输入"first last"名称或"(409) 555-1212"作为电话号码(带有"%s"scanf()不能(,您唯一的责任是验证返回,然后从输入中修剪尾部的'n'。验证返回以处理手动生成的EOF,其中用户通过在Linux上按Ctrl+d或在windows上按Ctrl+z来取消输入。(正如您也必须为scanf()做的那样(作为一个好处,您不需要输入'#'来结束输入,因为当单独按下enter时,fgets()读取'n',这允许您的用户只需在空的name行上按enter即可退出。

例如,您可以读取并验证姓名和电话号码字符串是否已使用以下简单内容输入:

#define MAXTEL  32      /* if you need a constant, #define one (or more) */
#define MAXNM   64
#define MAXEMP 128
typedef struct {
char name[MAXNM],
telno[MAXTEL];
} employee;
int readin (employee *emp)
{
int n;
for (n = 0; n < MAXEMP; n++) {  /* loop continually - protect array bounds */
fputs ("nEnter name: ", stdout);   /* prompt */
/* read/validate, check for Enter alone to exit */
if (!fgets (emp[n].name, MAXNM, stdin) || *emp[n].name == 'n')
break;
emp[n].name[strcspn(emp[n].name, "n")] = 0;    /* trim trailing n */
fputs ("Enter tel : ", stdout);                 /* prompt */
if (!fgets (emp[n].telno, MAXTEL, stdin))       /* read/validate */
break;
emp[n].telno[strcspn(emp[n].telno, "n")] = 0;  /* trim trailing n */
}
return n;
}

使用scanf((怎么样

这是可行的,但您的责任会急剧增加,因为您需要删除输入后保留在stdin中的'n',以确保离开readin()函数后代码中的下一次输入不会失败。使用scanf()(设置为循环,如您所示需要'#'来终止输入(将需要:

int readin (employee *emp)
{
int n;
for (n = 0; n < MAXEMP; n++) {  /* loop continually - protect array bounds */
int rtn;            /* variable to save the return of scanf */
fputs ("nEnter name: ", stdout);       /* prompt */
rtn = scanf(" %63[^n]", emp->name);    /* read into tmp saving return */
if (rtn == EOF) {   /* handle EOF - user presses Ctrl+d (Ctrl+z win) */
fputs ("(user canceled input)n", stderr);
break;
}
else if (rtn == 1 && *emp->name == '#') /* good input and '#' -- bail */
break;
for (;;) {  /* loop contianually until valid telno entered */
fputs ("Enter tel : ", stdout);         /* prompt */
rtn = scanf(" %31[^n]", emp->telno);   /* read saving return */
if (rtn == EOF) {       /* handle EOF - ditto */
fputs ("(user canceled input)n", stderr);
break;
}
else if (rtn == 1) {    /* good input */
/* further validate telno here */
break;
}
}   /* empty trailing n from stdin */
for (int c = getchar(); c != 'n' && c != EOF; c = getchar()) {}
emp++;  /* advance pointer */
}
return n;   /* return success */
}

您仍然需要输入一个'#'来终止输入——这应该不是必需的。

你更愿意用哪个

示例

使用以下任一功能:

int main (void) {
employee e[MAXEMP] = {{ .name = "" }};
int n = readin (e);
for (int i = 0; i < n; i++)
printf ("nemployee:n  name  : %sn  telno : %sn", 
e[i].name, e[i].telno);
}

示例使用/输出-fgets((

$ ./bin/empnametelnoarray
Enter name: John Q. Public
Enter tel : 444-1212
Enter name: Sally P. Public
Enter tel : 444-1222
Enter name: Mary Jane
Enter tel : 444-1223
Enter name:
employee:
name  : John Q. Public
telno : 444-1212
employee:
name  : Sally P. Public
telno : 444-1222
employee:
name  : Mary Jane
telno : 444-1223

示例使用/输出-扫描((

$ ./bin/empnametelnoarray
Enter name: John Q. Public
Enter tel : 444-1212
Enter name: Sally P. Public
Enter tel : 444-1222
Enter name: Mary Jane
Enter tel : 444-1223
Enter name: #
employee:
name  : John Q. Public
telno : 444-1212
employee:
name  : Sally P. Public
telno : 444-1222
employee:
name  : Mary Jane
telno : 444-1223

完整的示例如下所示,只需将-DUSESCANF添加到编译字符串中(或为VS添加/D USESCANF(即可使用scanf()版本,默认情况下使用fgets()。总的来说,没有理由使用scanf()来读取用户输入的两个字符串。使用面向行的输入功能读取用户的输入行会更好:

#include <stdio.h>
#include <string.h>
#define MAXTEL  32      /* if you need a constant, #define one (or more) */
#define MAXNM   64
#define MAXEMP 128
typedef struct {
char name[MAXNM],
telno[MAXTEL];
} employee;
#ifndef USESCANF
int readin (employee *emp)
{
int n;
for (n = 0; n < MAXEMP; n++) {  /* loop continually - protect array bounds */
fputs ("nEnter name: ", stdout);   /* prompt */
/* read/validate, check for Enter alone to exit */
if (!fgets (emp[n].name, MAXNM, stdin) || *emp[n].name == 'n')
break;
emp[n].name[strcspn(emp[n].name, "n")] = 0;    /* trim trailing n */
fputs ("Enter tel : ", stdout);                 /* prompt */
if (!fgets (emp[n].telno, MAXTEL, stdin))       /* read/validate */
break;
emp[n].telno[strcspn(emp[n].telno, "n")] = 0;  /* trim trailing n */
}
return n;
}
#else
int readin (employee *emp)
{
int n;
for (n = 0; n < MAXEMP; n++) {  /* loop continually - protect array bounds */
int rtn;            /* variable to save the return of scanf */
fputs ("nEnter name: ", stdout);       /* prompt */
rtn = scanf(" %63[^n]", emp->name);    /* read into tmp saving return */
if (rtn == EOF) {   /* handle EOF - user presses Ctrl+d (Ctrl+z win) */
fputs ("(user canceled input)n", stderr);
break;
}
else if (rtn == 1 && *emp->name == '#') /* good input and '#' -- bail */
break;
for (;;) {  /* loop contianually until valid telno entered */
fputs ("Enter tel : ", stdout);         /* prompt */
rtn = scanf(" %31[^n]", emp->telno);   /* read saving return */
if (rtn == EOF) {       /* handle EOF - ditto */
fputs ("(user canceled input)n", stderr);
break;
}
else if (rtn == 1) {    /* good input */
/* further validate telno here */
break;
}
}   /* empty trailing n from stdin */
for (int c = getchar(); c != 'n' && c != EOF; c = getchar()) {}
emp++;  /* advance pointer */
}
return n;   /* return success */
}
#endif
int main (void) {
employee e[MAXEMP] = {{ .name = "" }};
int n = readin (e);
for (int i = 0; i < n; i++)
printf ("nemployee:n  name  : %sn  telno : %sn", 
e[i].name, e[i].telno);
}

仔细看看,如果你还有问题,请告诉我。

最新更新