大家好我刚刚开始学习如何使用指针而且我的代码卡住了。我需要编写一个修改的代码(纠正大写和小写,找出每个公民的年份)并对公民名单进行排序。例如,如果用户条目是:
4 //只是公民人数
lAna lanIc 1999
lana lanac 1999
laNa LaneC 1989
lAna lanOc 1999
显示必须是:
18; Lanac,Lana
18; Lanic,Lana
18; Lanoc,Lana
28; Lanec,Lana
#include <stdio.h>
#include <string.h>
#include <ctype.h>
typedef struct {
char name[26];
char surname[26];
int birth;
} citizen; //the structer for the citizen
void modify(citizen *g);
int compare(citizen g1, citizen g2); //compares citizens by birth or surname or name
void sort(citizen g[], int); //insertion sort
int main()
{
int n, i;
citizen g[100];
scanf("%d", &n);
for(i = 0; i < n; i++) {
scanf("%s %s %d", g[i].name, g[i].surname, &g[i].birth);
modify(g + i);
}
sort(g, n);
for (i = 0; i < n; i++) {
printf("%2d; %s %s\n", g[i].birth, g[i].surname, g[i].name);
}
return 0;
}
void modify(citizen *g) { //here I'm having trouble
int i = 0;
//trying to correct the name
if(isalpha(*g[i].name[0])) {
*g[i].name[0] = toupper(*g[i].name[0]);
}
for(i = 1; i < strlen(*g[i].name); i++) {
*g[i].name = toupper(*g[i].name);
}
//then the surname
if(isalpha(*g[i].surname[0])) {
*g[i].surnma[0] = toupper(*g[i].surname[0]);
}
for(i = 1; i < strlen(*g[i].surname); i++) {
*g[i].surname = toupper(*g[i].surname);
}
*g[i].birth = 2017 - *g[i].birth; //finding how old is the citizen
}
int compare(citizen g1, citizen g2) {
if(g1.birth == g2.birth) {
if(!strcmp(g1.surname, g2.surname)) {
return strcmp(g1.name,g2.name);
}
else {
return strcmp(g1.surname, g2.surname);
}
}
else if (g1.birth > g2.birth) {
return 1;
}
return -1;
}
void sort(citizen g[], int n) { //insertion sort
int i, j;
citizen tmp;
for(i = 0; i < n; i++) {
tmp = g[i];
j = i;
while(j > 0 && compare(g[j-1], tmp)) {
g[j] = g[j - 1];
j--;
}
g[j] = tmp;
}
}
答案 0 :(得分:1)
基础知识:
在你的主要功能中:
citizen g[100];
宣布一个由100名公民组成的阵列。 g
是一个不是指针的数组。
在修改功能
中modify(citizen *g)
g
是指向公民的指针。它不是一个数组。所以你可能会问为什么这样做是合法的:
modify(g + i);
原因是,在表达式中使用g
的上下文中,编译器将其转换为指向其第一个元素的指针。我们说“g
将衰减到指向其第一个元素的指针”。
有两种方法可以访问指针指向的东西(我们说“取消引用指针”)。第一种是使用*
运算符。如果p
为int*
我们可以
int x = *p;
如果p
指向int
数组中的int
,我们可以进行指针运算。所以我们可以做到
int y = *(p + 3);
int z = *(p - 2);
如果p
指向数组中至少大小为6的第三个元素,y
现在具有与第六个元素相同的值,z
具有与第六个元素相同的值第一要素。
取消引用指针的第二种方法是使用下标语法。语法p[i]
完全等同于*(p + i)
,我的意思是完全。添加是可交换的p + i == i + p
,这意味着*(p + i) == *(i + p)
意味着(这在C中是合法的)p[i] == i[p]
无论如何,上述每个陈述都可以使用下标来编写
int x = p[0];
int y = p[3];
int z = p[-2];
除了保存我们的理智之外,如果p是指向数组的第一个元素或malloc'd块的第一个元素的指针,我们倾向于仅使用下标语法。
如果p
是指向struct
的指针(就像您的citizen
结构一样,则可以通过取消引用p
并使用正常的diot语法来访问结构中的字段
int myBirth = (*p).birth;
括号是必要的,因为点运算符通常具有比*运算符更高的优先级。对于*p.birth
,C编译器认为p
是一个带有名为birth
的字段的结构,它试图将其作为指针取消引用。 C为(*p).birth
事物
int myBirth = p->birth; // Exactly equivalent to (*).birth
最后在C中,您可以使用&amp;获取指向任意对象的指针。运营商。
int x = 0;
int* p = &x; // p is a pointer to x.
因此,当我们说g
衰减到指向其第一个元素的指针时,我们的意思是编译器转换
modify(g + i);
要 修改(&amp; g [0] + i);
所以,你看,你的修改函数接收到一个指向g
元素的指针。看看函数的前几行:
if(isalpha(*g[i].name[0])) {
*g[i].name[0] = toupper(*g[i].name[0]);
}
Because i is 0 at this point, `g[i].name` is the same as `(*g).name` or `g->name`. Use the last one for clarity. The `name` field is an array of chars, so `name[0]` is the first character of the name, which is what you want. You have an extra dereference with the leading * that you don't need. The above should be
if (isalpha(g->name[0])) {
g->name[0] = toupper(g->name[0]);
}
除了toupper
isalpha
执行 g->name[0] = toupper(g->name[0]);
检查,所以这一切都变为
for(i = 1; i < strlen(*g[i].surname); i++) {
*g[i].surname = toupper(*g[i].surname);
}
我会留给你修复剩下的功能,除了在这里提到相当糟糕的错误:
{{1}}
这对我来说根本没有意义。
答案 1 :(得分:0)
我会在这里给你答案,而不是取消引用你的方式:
void modify(citizen *g) { //here I'm having trouble
int i = 0;
//trying to correct the name
//Is this really necessary?
if (isalpha(g->name[0])) {
g->name[0] = toupper(g->name[0]);
}
for (i = 1; i < strlen(g->name); i++) {
g->name[i] = toupper(g->name[i]);
}
//then the surname
//Is this really necessary?
if (isalpha(g->surname[0])) {
g->surname[0] = toupper(g->surname[0]);
}
for (i = 1; i < strlen(g->surname); i++) {
g->surname[i] = toupper(g->surname[i]);
}
g->birth = 2017 - g->birth; //finding how old is the citizen
}
我还修改了你compare
函数:
int compare(citizen *g1, citizen *g2) {
if (g1->birth == g2->birth) {
int resp = strcmp(g1->surname, g2->surname);
if (!resp) {
return strcmp(g1->name, g2->name);
}
return resp;
} else if (g1->birth > g2->birth) {
return 1;
}
return -1;
}