如何在我的代码中正确使用指针?

时间:2017-05-10 08:48:26

标签: c

大家好我刚刚开始学习如何使用指针而且我的代码卡住了。我需要编写一个修改的代码(纠正大写和小写,找出每个公民的年份)并对公民名单进行排序。例如,如果用户条目是:

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;

     }
 }  

2 个答案:

答案 0 :(得分:1)

基础知识:

在你的主要功能中:

citizen g[100];

宣布一个由100名公民组成的阵列。 g是一个不是指针的数组。

在修改功能

modify(citizen *g)

g是指向公民的指针。它不是一个数组。所以你可能会问为什么这样做是合法的:

modify(g + i);

原因是,在表达式中使用g的上下文中,编译器将其转换为指向其第一个元素的指针。我们说“g 衰减到指向其第一个元素的指针”。

有两种方法可以访问指针指向的东西(我们说“取消引用指针”)。第一种是使用*运算符。如果pint*我们可以

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;
}