#include<stdio.h>
#include<stdio.h>
#include<string.h>
struct stud
{
char nam[20];
int num;
char letter[5];
};
int main()
{
struct stud s[5];
int i, j;
for(i = 0; i < 5; i ){
printf("Enter the name of student #%d: ", i 1);
scanf("%s", s[i].nam);
printf("Enter the number grade of student #%d: ", i 1);
scanf("%d", &s[i].num);
}
for (j = 0; j < i; j ) {
if (strcmp(s[i].nam, s[j].nam) == 0)
printf("Error. Duplicate name detected.");
}
for(i = 0; i < 5; i ){
if(s[i].num >= 90 )
strcpy(s[i].letter, "A");
else if(s[i].num >= 80)
strcpy(s[i].letter, "B");
else if(s[i].num >= 70)
strcpy(s[i].letter, "C");
else if(s[i].num >= 60)
strcpy(s[i].letter, "D");
else
strcpy(s[i].letter, "F");
}
for(i = 0; i < 5; i )
printf("\n%s has a %s ", s[i].nam, s[i].letter);
return 0;
}
該程式讓用戶輸入 5 個姓名和 5 個數字等級,然后輸出該學生各自的字母等級。我正在嘗試這樣做,如果用戶輸入重復的名稱,則會列印訊息說他們不能這樣做。我嘗試這樣做的嘗試如下:
for (j = 0; j < i; j ) {
if (strcmp(s[i].nam, s[j].nam) == 0)
printf("Error. Duplicate name detected.");
}
我認為 s[j] 是前一個字串,并比較它是否等于 0(重復)并列印一條訊息。但是這顯然不起作用,所以我想知道如何解決這個問題,以便它可以正確檢測重復的名稱。謝謝你。
我之前也發布過這個問題,但提供解釋的人在我提供更多問題并要求澄清之前洗掉了他們的回復。因此,我再次發布此內容,試圖就我在代碼中做錯的事情尋求進一步的幫助。
uj5u.com熱心網友回復:
- 在檢測回圈開始時,
i已經是 5,所以 usings[i]是未定義的行為 - 在您的檢測回圈中,
i是不變的。您只是將名稱與最后一個名稱進行比較[當然,UB 除外]。
您需要兩個回圈來比較所有名稱。
此外,5到處使用是一個“神奇的數字”。最好使用#define(例如SMAX)
在下面的代碼中,我使用cpp條件來表示舊代碼和新代碼:
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
這是更正后的代碼。它帶有錯誤和修復注釋:
#include <stdio.h>
#include <stdio.h>
#include <string.h>
struct stud {
char nam[20];
int num;
char letter[5];
};
#define SMAX 5 // maximum number of students
int
main()
{
struct stud s[SMAX];
int i, j;
for (i = 0; i < SMAX; i ) {
printf("Enter the name of student #%d: ", i 1);
scanf("%s", s[i].nam);
printf("Enter the number grade of student #%d: ", i 1);
scanf("%d", &s[i].num);
}
// NOTE/BUG: i is already SMAX, so using s[i] is UB (undefined behavior)
// NOTE/BUG: i never changes
#if 0
for (j = 0; j < i; j ) {
if (strcmp(s[i].nam, s[j].nam) == 0)
printf("Error. Duplicate name detected.");
}
#else
for (i = 0; i < (SMAX - 1); i ) {
for (j = i 1; j < SMAX; j ) {
if (strcmp(s[i].nam, s[j].nam) == 0)
printf("Error. Duplicate name detected -- %s\n",s[j].nam);
}
}
#endif
for (i = 0; i < SMAX; i ) {
if (s[i].num >= 90)
strcpy(s[i].letter, "A");
else if (s[i].num >= 80)
strcpy(s[i].letter, "B");
else if (s[i].num >= 70)
strcpy(s[i].letter, "C");
else if (s[i].num >= 60)
strcpy(s[i].letter, "D");
else
strcpy(s[i].letter, "F");
}
// NOTE/BUG: newline should go at the end of the printf to prevent a hanging
// last line
#if 0
for (i = 0; i < SMAX; i )
printf("\n%s has a %s ", s[i].nam, s[i].letter);
#else
for (i = 0; i < SMAX; i )
printf("%s has a %s\n", s[i].nam, s[i].letter);
#endif
return 0;
}
更新:
謝謝你的提示!在旁注中,當用戶輸入重復的姓名時,我將如何做到這一點,出現錯誤訊息并且程式就在那里結束。例如:輸入學生 1 的姓名:dan 輸入成績:87 輸入學生的姓名學生 2:dan 輸入年級:78 錯誤。不允許重名。然后程式到此結束。– 用戶234567
很容易。我將重復檢測代碼放入函式中。
但是,我添加了更多增強功能,因此這可能會幫助您學習 ;-)
如果用戶輸入重復項,我添加了重新提示用戶。
我討厭
scanf;-) 我通過將提示代碼放入兩個函式來重新撰寫提示代碼。如果輸入是檔案,它會更好地作業。這在測驗期間很有用I changed the conversion from grade number to grade letter to use a table.
Anyway, here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
struct stud {
char nam[20];
int num;
char letter[5];
};
struct letter {
int num;
const char *letter;
};
#define LET(_num,_let) \
{ .num = _num, .letter = _let }
struct letter letters[] = {
LET(90,"A"),
LET(80,"B"),
LET(70,"C"),
LET(60,"D"),
LET(0,"F"),
LET(0,NULL)
};
#define SMAX 5 // maximum number of students
// chkall -- check entire array for duplicates
int
chkall(const struct stud *s,int smax)
{
int i;
int j;
int dup = 0;
for (i = 0; i < (smax - 1); i ) {
for (j = i 1; j < smax; j ) {
if (strcmp(s[i].nam, s[j].nam) == 0) {
printf("Error. Duplicate name detected -- %s\n",s[j].nam);
dup = 1;
}
}
}
return dup;
}
// chkone -- check a given entry for duplicate (as they are added)
int
chkone(const struct stud *s,int i)
{
int j;
int dup = 0;
for (j = 0; j < i; j ) {
if (strcmp(s[i].nam, s[j].nam) == 0) {
printf("Error. Duplicate name detected -- %s\n",s[j].nam);
dup = 1;
}
}
return dup;
}
// prompt_string -- prompt user for a string
char *
prompt_string(const char *what,int i,char *buf,size_t siz)
{
static int tty = -1;
// decide if our input is tty or file
if (tty < 0) {
struct winsize ws;
tty = ioctl(0,TIOCGWINSZ,&ws);
tty = (tty >= 0);
}
printf("Enter the %s of student #%d: ", what, i 1);
fflush(stdout);
char *cp = fgets(buf,siz,stdin);
do {
// handle EOF
if (cp == NULL)
break;
buf[strcspn(buf,"\n")] = 0;
// echo the data if input is _not_ a tty
if (! tty)
printf("%s\n",buf);
} while (0);
return cp;
}
// prompt_number -- prompt user for a number
long long
prompt_number(const char *what,int i)
{
char *cp;
char buf[100];
long long val;
while (1) {
cp = prompt_string(what,i,buf,sizeof(buf));
// handle EOF
if (cp == NULL) {
val = -1;
break;
}
// decode the number
val = strtoll(buf,&cp,10);
if (*cp == 0)
break;
printf("invalid number syntax -- '%s'\n",cp);
}
return val;
}
int
main(void)
{
struct stud s[SMAX];
int i;
for (i = 0; i < SMAX; i ) {
while (1) {
prompt_string("name",i,s[i].nam,sizeof(s[i].nam));
if (! chkone(s,i))
break;
}
s[i].num = prompt_number("number grade",i);
}
// recheck all entries
// this will _never_ report a duplicate because of the chkone above
chkall(s,SMAX);
for (i = 0; i < SMAX; i ) {
for (struct letter *let = letters; let->letter != NULL; let) {
if (s[i].num >= let->num) {
strcpy(s[i].letter,let->letter);
break;
}
}
}
for (i = 0; i < SMAX; i )
printf("%s has a %s\n", s[i].nam, s[i].letter);
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/453406.html
