C中的结构安排
Structure Arranging in C
我正在尝试制作一个程序来按人员 ID 排列我的结构。
我使用 long double 因为 ID 有 20 位数字长。
比如我介绍3个人:
1.Alex Alex / id = 219(...)
2.John John / id = 200(...)
3.Robert Robert / id = 199(...)
我希望我的程序重新排列,让罗伯特排在第一位,约翰排在第二位,亚历克斯排在第三位。
我在 "for" 结构上遇到问题 - 我不知道如何交换两个结构,因为我结合了字符和整数。
typedef struct
{
char name;
char prename;
long double id;
int j;
} PERSON;
int main()
{
int n,i,j;
printf ("How many people = ");
scanf("%d", &n);
PERSON v[n];
for(i=1;i<=n;i++)
{
printf("For person number nr. %d\n", i);
printf("name = ");
scanf("%s", &v[i].name);
printf("Prename = ");
scanf("%s", &v[i].prename);
printf("id = ");
scanf("%d", &v[i].id);
}
for(int i=0; i<n; i++)
{
for(int j=0; j<n-1; j++)
{
if( v[i].id > v[j+1].id )
{
int temp = v[j].id;
char temp2[100];
char temp3[100];
strcpy(v[j].prename,temp3);
strcpy(v[j].name,temp2);
v[j].id = v[j+1].id;
v[j+1].id = temp;
}
}
}
return;
}
您的代码的主要问题在于:
typedef struct
char name; <--- just a char! no room for a string
char prename; <--- just a char! no room for a string
long double id;
int j;
} PERSON;
您需要制作这些数组,以便它们可以保存名称。
喜欢:
#define MAX_NAME_LEN 100
typedef struct {
char name[MAX_NAME_LEN];
char prename[MAX_NAME_LEN];
long double id;
int j;
} PERSON;
除此之外,您应该始终检查 scanf
返回的值,并且 永远不要 执行 scanf("%s", &v[i].prename);
因为它可能导致缓冲区溢出。相反做 scanf("%99s", v[i].prename);
但更好地使用 fgets
对于排序...只需使用 qsort
- 参见 http://man7.org/linux/man-pages/man3/qsort.3.html
顺便说一句:无法使用 scanf("%d", &v[i].id);
扫描 long double
- %d
用于整数。也就是说,我怀疑你想使用 long double
。您可能想要一些整数类型 - 也许 long long unsigned
或 uint64_t
好的,因为您在这里所做的很多事情对于新的 C 开发人员来说并不明显,我想指出它们以帮助您学习:
typedef struct
{
// These need to be arrays if they are to be strings
// Preferably using a constant for size or dynamic
// if you want them to be variable sized to match input.
char name;
char prename;
// Do not use floating point numbers to represent integer values.
// IRL, you'd use a library, but here, you may want to use an array of
// some sort of integer type instead.
long double id;
// This is a really poor name for a struct variable and probably shouldn't be here.
int j;
} PERSON;
int main()
{
int n,i,j;
printf ("How many people = ");
// Dropping raw output from scanf into a memory allocation is crazy dangerous.
// At least error check the results to be sure it is meaningful.
scanf("%d", &n);
// This is a variable length array and often is not supported directly.
// You probably want to use a malloc()/free() pair to handle this.
// (Update: VLA is now part of newer standards, but are not safe because they cannot fail gracefully on out of memory.)
PERSON v[n];
// Anytime in C I see an array start at 1 and use <= for condition, I get very nervous because
// it tends to lead to indexing errors.
for(i=1;i<=n;i++)
{
printf("For person number nr. %d\n", i);
printf("name = ");
// Oops - and this is why. You just skipped the first entry at 0
// and will overwrite memory on the last loop.
// Also, scanf into a string without a length can blow up memory...
scanf("%s", &v[i].name);
printf("Prename = ");
// Ditto
scanf("%s", &v[i].prename);
printf("id = ");
// Ditto - worse because you've crossed your types - %d doesn't go into a long double.
scanf("%d", &v[i].id);
}
// Should be its own function to make it easier to swap later to a better sort.
for(int i=0; i<n; i++)
{
// Bubble sort usually wants j=i here.
for(int j=0; j<n-1; j++)
{
if( v[i].id > v[j+1].id )
{
// Make a swap function here. Makes it clearer what you want to do.
int temp = v[j].id;
// What is 100? How do you know that is enough?
// These are called magic numbers and lead to code death.
char temp2[100];
char temp3[100];
// Ah, strcpy - 3 things wrong here.
// 1 - You have the parameters backwards - you are copying temp3 to your struct.
// 2 - You have no way to know if the destination will fit the source because it copies until it finds a '[=10=]' - very dangerous.
// 3 - Because your parameters are backwards and temp123 is not initialized, this very well could copy forever.
// strncpy (also crazy dangerous) at the least should be used and consider using better means like strlcpy() and such.
strcpy(v[j].prename,temp3);
strcpy(v[j].name,temp2);
v[j].id = v[j+1].id;
v[j+1].id = temp;
// You kinda forgot to swap the strings, but the program is already dead so no worries.
}
}
}
// Please enable compiler warnings - you must return a value here.
return;
}
说真的,我确定我错过了其他一些东西,但这对于免费的互联网代码审查和学习来说已经足够了 session。 :)
关于 strcpy() 和 strncpy() 的信息
Why is strncpy insecure?
关于 scanf() 安全的信息
How to prevent scanf causing a buffer overflow in C?
关于可变长度数组安全的信息:
Is it safe to use variable-length arrays?
我正在尝试制作一个程序来按人员 ID 排列我的结构。 我使用 long double 因为 ID 有 20 位数字长。 比如我介绍3个人:
1.Alex Alex / id = 219(...)
2.John John / id = 200(...)
3.Robert Robert / id = 199(...)
我希望我的程序重新排列,让罗伯特排在第一位,约翰排在第二位,亚历克斯排在第三位。 我在 "for" 结构上遇到问题 - 我不知道如何交换两个结构,因为我结合了字符和整数。
typedef struct
{
char name;
char prename;
long double id;
int j;
} PERSON;
int main()
{
int n,i,j;
printf ("How many people = ");
scanf("%d", &n);
PERSON v[n];
for(i=1;i<=n;i++)
{
printf("For person number nr. %d\n", i);
printf("name = ");
scanf("%s", &v[i].name);
printf("Prename = ");
scanf("%s", &v[i].prename);
printf("id = ");
scanf("%d", &v[i].id);
}
for(int i=0; i<n; i++)
{
for(int j=0; j<n-1; j++)
{
if( v[i].id > v[j+1].id )
{
int temp = v[j].id;
char temp2[100];
char temp3[100];
strcpy(v[j].prename,temp3);
strcpy(v[j].name,temp2);
v[j].id = v[j+1].id;
v[j+1].id = temp;
}
}
}
return;
}
您的代码的主要问题在于:
typedef struct
char name; <--- just a char! no room for a string
char prename; <--- just a char! no room for a string
long double id;
int j;
} PERSON;
您需要制作这些数组,以便它们可以保存名称。
喜欢:
#define MAX_NAME_LEN 100
typedef struct {
char name[MAX_NAME_LEN];
char prename[MAX_NAME_LEN];
long double id;
int j;
} PERSON;
除此之外,您应该始终检查 scanf
返回的值,并且 永远不要 执行 scanf("%s", &v[i].prename);
因为它可能导致缓冲区溢出。相反做 scanf("%99s", v[i].prename);
但更好地使用 fgets
对于排序...只需使用 qsort
- 参见 http://man7.org/linux/man-pages/man3/qsort.3.html
顺便说一句:无法使用 scanf("%d", &v[i].id);
扫描 long double
- %d
用于整数。也就是说,我怀疑你想使用 long double
。您可能想要一些整数类型 - 也许 long long unsigned
或 uint64_t
好的,因为您在这里所做的很多事情对于新的 C 开发人员来说并不明显,我想指出它们以帮助您学习:
typedef struct
{
// These need to be arrays if they are to be strings
// Preferably using a constant for size or dynamic
// if you want them to be variable sized to match input.
char name;
char prename;
// Do not use floating point numbers to represent integer values.
// IRL, you'd use a library, but here, you may want to use an array of
// some sort of integer type instead.
long double id;
// This is a really poor name for a struct variable and probably shouldn't be here.
int j;
} PERSON;
int main()
{
int n,i,j;
printf ("How many people = ");
// Dropping raw output from scanf into a memory allocation is crazy dangerous.
// At least error check the results to be sure it is meaningful.
scanf("%d", &n);
// This is a variable length array and often is not supported directly.
// You probably want to use a malloc()/free() pair to handle this.
// (Update: VLA is now part of newer standards, but are not safe because they cannot fail gracefully on out of memory.)
PERSON v[n];
// Anytime in C I see an array start at 1 and use <= for condition, I get very nervous because
// it tends to lead to indexing errors.
for(i=1;i<=n;i++)
{
printf("For person number nr. %d\n", i);
printf("name = ");
// Oops - and this is why. You just skipped the first entry at 0
// and will overwrite memory on the last loop.
// Also, scanf into a string without a length can blow up memory...
scanf("%s", &v[i].name);
printf("Prename = ");
// Ditto
scanf("%s", &v[i].prename);
printf("id = ");
// Ditto - worse because you've crossed your types - %d doesn't go into a long double.
scanf("%d", &v[i].id);
}
// Should be its own function to make it easier to swap later to a better sort.
for(int i=0; i<n; i++)
{
// Bubble sort usually wants j=i here.
for(int j=0; j<n-1; j++)
{
if( v[i].id > v[j+1].id )
{
// Make a swap function here. Makes it clearer what you want to do.
int temp = v[j].id;
// What is 100? How do you know that is enough?
// These are called magic numbers and lead to code death.
char temp2[100];
char temp3[100];
// Ah, strcpy - 3 things wrong here.
// 1 - You have the parameters backwards - you are copying temp3 to your struct.
// 2 - You have no way to know if the destination will fit the source because it copies until it finds a '[=10=]' - very dangerous.
// 3 - Because your parameters are backwards and temp123 is not initialized, this very well could copy forever.
// strncpy (also crazy dangerous) at the least should be used and consider using better means like strlcpy() and such.
strcpy(v[j].prename,temp3);
strcpy(v[j].name,temp2);
v[j].id = v[j+1].id;
v[j+1].id = temp;
// You kinda forgot to swap the strings, but the program is already dead so no worries.
}
}
}
// Please enable compiler warnings - you must return a value here.
return;
}
说真的,我确定我错过了其他一些东西,但这对于免费的互联网代码审查和学习来说已经足够了 session。 :)
关于 strcpy() 和 strncpy() 的信息 Why is strncpy insecure?
关于 scanf() 安全的信息 How to prevent scanf causing a buffer overflow in C?
关于可变长度数组安全的信息: Is it safe to use variable-length arrays?