C 如何在代码中正确使用指针?
大家好,我刚开始学习如何使用指针,我陷入了我的代码中。我需要编写一个代码来修改(更正大小写并找出每个公民的年份)并对公民列表进行排序。例如,如果用户条目为: 4//仅仅是公民的数量 拉娜·拉尼奇1999 拉娜·拉纳克1999 拉娜·拉内克1989 拉娜拉诺克1999 显示器必须: 十八,;拉纳克,拉娜 十八,;拉尼奇,拉娜 十八,;拉娜,拉诺克 二十八,;拉内克,拉娜C 如何在代码中正确使用指针?,c,C,大家好,我刚开始学习如何使用指针,我陷入了我的代码中。我需要编写一个代码来修改(更正大小写并找出每个公民的年份)并对公民列表进行排序。例如,如果用户条目为: 4//仅仅是公民的数量 拉娜·拉尼奇1999 拉娜·拉纳克1999 拉娜·拉内克1989 拉娜拉诺克1999 显示器必须: 十八,;拉纳克,拉娜 十八,;拉尼奇,拉娜 十八,;拉娜,拉诺克 二十八,;拉内克,拉娜 #include <stdio.h> #include <string.h> #include <
#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;
}
}
#包括
#包括
#包括
类型定义结构{
字符名[26];
查氏[26];
婴儿出生;
}公民//公民的建构者
无效修改(公民*g);
int比较(公民g1、公民g2)//按出生、姓氏或姓名对公民进行比较
无效排序(公民g[],整数)//插入排序
int main()
{
int n,i;
公民g[100];
scanf(“%d”和“&n”);
对于(i=0;ig2.birth){
返回1;
}
返回-1;
}
void排序(citizen g[],int n){//插入排序
int i,j;
公民tmp;
对于(i=0;i0&&compare(g[j-1],tmp)){
g[j]=g[j-1];
j--;
}
g[j]=tmp;
}
}
我将在这里给您答案,而不是按您的方式取消引用指针:
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
}
基本要素:
在您的主要功能中:
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块的第一个元素的指针,我们倾向于只使用下标语法
如果p
是指向struct
的指针(就像您的citizen
结构一样),您可以通过取消引用p
并使用正常的diot语法来访问结构中的字段
int myBirth = (*p).birth;
圆括号是必需的,因为点运算符通常比*运算符具有更高的优先级。对于*p.birth
,C编译器认为p
s是一个结构,其中有一个名为birth
的字段,它试图将该字段作为指针取消引用。C为(*p)提供了一种快捷语法.出生
是什么
int myBirth = p->birth; // Exactly equivalent to (*).birth
最后,在C中,您可以使用&运算符获得指向任意对象的指针
int x = 0;
int* p = &x; // p is a pointer to x.
所以当我们说g
衰减为指向其第一个元素的指针时,我们的意思是编译器转换
modify(g + i);
到
修改(&g[0]+i)
因此,您可以看到,modify函数接收到一个指向g
元素的指针。查看函数的前几行:
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;
}
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);
}
for(i=1;i
这对我来说毫无意义。现在怎么办,C或C?@tilz0R哦,对不起,这是C或C?因为在我看来它真的不像C。你也可以给每个人一个味道,并正确地缩进你的代码。你的问题是什么?@UnholySheep我应该如何在函数修改中使用指针?现在,你让他非常高兴地发现如何修改通过阅读一本好的手册,正确地用C语言编写指针程序……至少,你给了他一个任务,让他自己找出如何将非第一个字符格式化为小写