2017-02-19 6 views
0

Я независимо друг от друга обучения C. У меня есть четыре-структуру члена следующим образом:C Структуры: Печатное элемент строки производит странные результаты

#define aSize 10 
struct Students { 
    char lastName[aSize]; 
    char firstName[aSize]; 
    int age; 
    int grade; 
} 

У меня есть две отдельные функции (в файле main.c):

void pasteInfo_1(struct Students S1) {} 

и

void printStudents(struct Students S1) {} 

pasteInfo() использует strcpy() и назначение присваивать значения членам; printStudents() затем печатает значения, хранящиеся в элементах. Когда я скомпилирую файл:

#in makefile 
CFLAGS = -lm -o -Wall 
gcc main.c $(CFLAGS) main 

Он компилируется без ошибок. Однако, когда я вызываю исполняемый файл, он печатает некоторые очень странные символы, которые выглядят как бинарные/сборочные. Какие-либо предложения? Вот отдельные функции.

void pasteInfo_1(struct Students S1) { 
    strcpy(S1.lastName, "Effinger"); 
} 

А вот printStudents:

void printStudents(struct Students S1) { 
    printf("%s\n",S1.lastName); 
} 

вызовов функций в основной:

int main() { 
    struct Students S1; 
    pasteInfo_1(S1); 
    printStudents(S1); 
} 

Re: Модификации. После добавления изменения, предложенные user3629249, я получил следующие ошибки:

main.c: 6: 23: предупреждение: «Struct Студенты», объявленная внутри списка параметров не будет виден за пределами этого определения или объявления недействительным pasteInfo (struct Students * pS1); ^ ~~~~~~~ main.c: 7: 27: warning: 'struct Studens' объявленный внутренний список параметров не будет виден вне этого определения или объявления void printStudents (struct Studens S1); ^ ~~~~~~ main.c: В функции 'main': main.c: 22: 14: warning: передать аргумент 1 из 'pasteInfo' из несовместимого типа указателя [-Wincompatible-pointer-types] pasteInfo (& S1); ^ main.c: 6: 6: note: expected 'struct Students *', но аргумент имеет тип 'struct Students *' void pasteInfo (struct Students * pS1); ^ ~~~~~~~~ main.c: 23: 17: ошибка: тип формального параметра 1 не заполнен printStudents (S1); ^ ~ main.c: На верхнем уровне: main.c: 26: 6: Ошибка: конфликтующие типы для '' pasteInfo ничтожной pasteInfo (Struct Студенты * PS1) ^ ~~~~~~~~ основной .c: 6: 6: note: предыдущее объявление 'pasteInfo' было здесь void pasteInfo (struct Students * pS1); ^ ~~~~~~~~ main.c: 32: 6: ошибка: конфликтующие типы для 'printStudents' void printStudents (struct Students S1) ^ ~~~~~~~~~~~~ main.c: 7: 6: note: предыдущая декларация 'printStudents' была здесь void printStudents (struct Studens S1); ^ ~~~~~~~~~~~~

ответ

3

I am independently learning C.

Что это значит? Вы читаете из книги? Если да, то какая книга?

Имейте в виду, что опасно изучать С путем ошибочного проб и ошибок; то, что вы, скорее всего, окажетесь в процессе обучения, - это то, что отличается от C тончайшими и, возможно, опасными способами, и какие лекарства лучше всего справляются с головными болями, которые вы даете себе ...

Проблема, с которой вы столкнулись, связана с по значению. Когда вы вызываете свою функцию, создается копия вашей структуры, и эта копия - это то, что вы изменяете в своей вызываемой функции. Следовательно, исходная структура внутри вызывающего абонента (main) переходит в немодифицированную, и, печатая с этого неинициализированного объекта, вы вызываете неопределенное поведение. В качестве руководства я могу сказать вам, что можно попробовать вернуть измененную структуру обратно в main, а затем присвоить это возвращаемое значение обратно S1, при условии, что вы используете компилятор, совместимый с C99 (что не так много, чтобы спросить , в этот день и в возрасте).

Это опасность обучения ошибочным испытанием и ошибкой; вы столкнетесь с большим количеством неопределенного поведения (и поведения, определенного реализацией), которое будет отличаться от системы к системе и может не иметь смысла в то время ... Вам лучше избегать UB и IB, читая приличную книгу, такую как K & R2E, и выполняя упражнения, когда вы натыкаетесь на них.

+0

«* Имейте в виду, что это опасно, чтобы узнать C по дезинформированной проб и ошибок *» - я бы хотел что это в значительной степени то, как я учил себя C в детстве, и я хотел бы думать, что в любом случае я все равно в порядке. Не сказал, что рекомендую этот метод, просто говоря. :) – Dolda2000

+0

@ Dolda2000 Аналогичным образом, хотя позже я вернулся к книге (и по стандарту C) и сожалел, что не использовал их для начала. Мои исследования продвинулись бы намного быстрее! – Sebivor

+0

Ну ... Мой дедушка дает мне «проекты» (напишите код, который делает это и это). Верните структуру, а затем распечатайте ее. Спасибо! – Jordan

0

, когда вызываемая функция планирует (напрямую) изменить что-либо в функции вызывающего абонента, передать адрес элемента вызываемой функции. И.Е.

int main(void) 
{ 
    struct Students S1; 
    pasteInfo_1(&S1); // <-- passing pointer to struct 
    printStudents(S1); 
} 

Затем изменить) `функцию pasteInfo_1 (ожидать указатель,

void pasteInfo_1(struct Students * pS1) 
{ 
    strcpy(pS1->lastName, "Effinger"); 
} 

Обратите внимание на использование вертикального выравнивания фигурных скобок и использование соответствующего горизонтального расстояния.

Цель вертикального выравнивания и горизонтального интервала - сделать код более читаемым.

+0

Я попытался это сделать, но затем напечатал несколько ошибок: «warning: 'struct Объявленные пользователем внутренние списки параметров не будут видны вне этого определения или декларации void pasteInfo (struct Students * pS1);" Печатается так же для printStudents «Предупреждение: передайте один аргумент« pasteInfo »из несовместимого типа указателя [-Wincompatible-pointer-types] pasteInfo (&S1); – Jordan

+0

@Jordan, Ваш комментарий звучит так, будто вы отредактировали фактическое определение структуры , который (в общем случае) должен быть вставлен сразу после операторов '# include' – user3629249

+0

Я сохранил определение структуры.(Но я узнал, что прототипы идут за структурами) – Jordan

-1

Решено! Вот рабочий код: (Отдельное спасибо user3629249 и Себом за их советы)

'#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <strings.h> 

struct Students 
{ 
    char lastName[8]; 
    char firstName[6]; 
    int age; 
    int grade; 
}; 

void pasteInfo(struct Students *S1); 
void printStudnets(struct Students S1); 

int main(void) 
{ 

    struct Students S1; 
    pasteInfo(&S1); 
    printStudents(S1); 
} 
void pasteInfo(struct Students *S1) 
{ 
    strcpy(S1->lastName, "Effinger"); 
} 
void printStudent(struct Students S1) 
{ 
     printf("%s\n",S1.lastName); 
}  
+0

это не скомпилировано! Прототип 'printStudent()' не указан правильно. – user3629249

+0

Поле strut: 'lastName' объявляется как 8 символов, но значение, записываемое в него, равно 9 символам (помните конечный байт NUL). Оборотная сторона поля' lastName' приводит к неопределенному поведению и может привести к событие сбоя. – user3629249

+0

К счастью, фактический .c не имеет опечаток. – Jordan

 Смежные вопросы

  • Нет связанных вопросов^_^