Форум программистов, компьютерный форум, киберфорум
C для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.73/22: Рейтинг темы: голосов - 22, средняя оценка - 4.73
307 / 20 / 4
Регистрация: 01.05.2010
Сообщений: 250
1

Получить от пользователя фамилию и вывести из этого файла инициалы и год рождения этого человека

04.08.2011, 17:17. Показов 4164. Ответов 21
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте. Имеется файл, из которого считываются строки вида
Ivanov A.A. 1234.
Требуется получить от пользователя фамилию и вывести из этого файла инициалы и год рождения этого человека. Что сделано: построчное считывание из файла при помощи fgets, разбиение строки при помощи strtok. Не работает только strcmp из условия: допустим, ввожу 'Ivanov' и(по идее) условие должно выполняться только тогда, когда ps будет равен 'Ivanov', но оно выполняется ВСЕГДА. Где я напутал, есть какие-нибудь идеи? спасибо.

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
#include <conio.h>
#include <string.h>
 
int main()
{
    char str[256]={0}, name[256]={0};
    char *ps={0};
    int year=0; 
 
    FILE *f=fopen("input.txt", "r+");
    
    scanf("%s", name);
 
    while(!feof(f))
    {
        fgets (str , 256 , f);
        ps = strtok (str,".");
        while (ps != NULL)//
        {
            if((strcmp(name, ps))!=0)
            {       
                printf("%s\n",ps);
            }
            ps = strtok (NULL, ".");
        }
        
    }
 
    fclose(f);//закрываем файл
    getch();
    return 0;
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
04.08.2011, 17:17
Ответы с готовыми решениями:

Написать функцию генерации email (для этого запросить у пользователя имя, год рождения, почтовый сервер)
Написать функцию генерации email (для этого запросить у пользователя имя, год рождения, почтовый...

Запросить фамилию, имя и отчество пользователя, и вывести его фамилию и инициалы
Вот задание:Написать программу, которая запрашивает фамилию, имя и отчество, а выводит фамилию и...

Объявить структуру Humen, включающую имя человека, фамилию и год рождения
Объявить тип-структуру humen, включающую имя человека, фамилию и год рождения. Объявить два массива...

Описать тип-структуру «Человек», хранящую имя, фамилию и год рождения человека
Задание:Описать тип-структуру «Человек», хранящую имя, фамилию и год рождения человека. Описать...

21
848 / 190 / 18
Регистрация: 01.08.2011
Сообщений: 505
04.08.2011, 17:22 2
функция fgets() не удаляет '\n', поэтому считанная строка имеет вид: "......\n\0", да и при вызове strtok() в качестве разделителей нужно больше символов указывать, например, " ,.;:\t\n". Также при сравнении strcmp() регистр учитывается (на всякий случай)
0
307 / 20 / 4
Регистрация: 01.05.2010
Сообщений: 250
04.08.2011, 17:27  [ТС] 3
Цитата Сообщение от Olga_ Посмотреть сообщение
функция fgets() не удаляет '\n', поэтому считанная строка имеет вид: "......\n\0"
Что порекомендуете предпринять? Я, честно сказать, не понимаю, мешает ли это. Есть \n, ну и что? Почему условие-то выполняется?

Цитата Сообщение от Olga_ Посмотреть сообщение
да и при вызове strtiok() в качестве разделителей нужно больше символов указывать, например, " ,.;:\t\n"
А если не нужно по задаче? Вот незачем мне туда добавлять мусор еще, только запутаюсь. Или имеется ограничение, что меньше двух разделителей, например, нельзя указывать? На cppreference.com ничего не сказано об этом.

Цитата Сообщение от Olga_ Посмотреть сообщение
Также при сравнении strcmp() регистр учитывается (на всякий случай)
учтено
0
Эксперт С++
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
04.08.2011, 17:30 4
AK3RN, strcmp в случае равенства возвращает 0. Так что условие выполняется как-раз когда строки не равны.
1
Заблокирован
Автор FAQ
04.08.2011, 17:32 5
Согласласен
Цитата Сообщение от Olga_ Посмотреть сообщение
в качестве разделителей нужно больше символов указывать, например, " ,.;:\t\n"
Ещё лучше не юзать fgets а считывать в буфер всё содержимое файла, как видишь код от этого почти не меняется
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>
#include <conio.h>
#include <string.h>
 
int main()
{
        int year=0;     
 
        FILE *f=fopen("input.txt", "r+");
        printf("Enter name\r\n");
        char name[256]={0};
        scanf("%s", name);
 
        fseek(f,0,SEEK_END);
        int Len = ftell(f);
        fseek(f,0,SEEK_SET);
        char * str = new char[Len];
        fread(str,1,Len,f);
        fclose(f);
        str[Len] = '\0';
 
        char delim[] = " .,\r\n?!";
        char * ps = strtok (str,delim);
        while (ps != NULL)//
        {
            if((strcmp(name, ps))==0)
                printf("%s\n",ps);
            ps = strtok (NULL, delim);
        }
        getch();
        return 0;
}
0
848 / 190 / 18
Регистрация: 01.08.2011
Сообщений: 505
04.08.2011, 17:33 6
Цитата Сообщение от AK3RN Посмотреть сообщение
Что порекомендуете предпринять? Я, честно сказать, не понимаю, мешает ли это. Есть \n, ну и что? Почему условие-то выполняется?


А если не нужно по задаче? Вот незачем мне туда добавлять мусор еще, только запутаюсь. Или имеется ограничение, что меньше двух разделителей, например, нельзя указывать? На cppreference.com ничего не сказано об этом.

" .,;:\n\t" - это не мусор, это разделители слов. Смотрите, функция fgets() считала, например, строку "abc\n", Вы вызываете strtok с параметром ".", после этого ps="abc\n". Если это слово сравнить с "abc", то strcmp() скажет, что слова не равны, поэтому '\n' надо убрать. Вот код

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
#include <conio.h>
#include <string.h>
 
int main()
{
        char str[256]={0}, name[256]={0};
        char *ps={0};
        int year=0;     
 
        FILE *f=fopen("input.txt", "r+");
        
        scanf("%s", name);
 
        while(!feof(f))
        {
                fgets (str , 256 , f);
                ps = strtok (str," .,;:\n\t");
                while (ps != NULL)//
                {
                        if((strcmp(name, ps))!=0)
                        {               
                                printf("%s\n",ps);
                        }
                        ps = strtok (NULL, " .,;:\n\t");
                }
                
        }
 
        fclose(f);//закрываем файл
        getch();
        return 0;
}
0
Заблокирован
04.08.2011, 17:33 7
Вы не мучайтесь и перед использованием сравнения просто выведите на экран то, что сравниваете. И все станет ясно.
0
Заблокирован
Автор FAQ
04.08.2011, 17:34 8
Цитата Сообщение от grizlik78 Посмотреть сообщение
strcmp в случае равенства возвращает 0
- поддерживаю
0
848 / 190 / 18
Регистрация: 01.08.2011
Сообщений: 505
04.08.2011, 17:37 9
Цитата Сообщение от grizlik78 Посмотреть сообщение
AK3RN, strcmp в случае равенства возвращает 0. Так что условие выполняется как-раз когда строки не равны.
Да, и это тоже конечно, что-то я упустила этот момент, спасибо

Добавлено через 1 минуту
Цитата Сообщение от Сыроежка Посмотреть сообщение
Вы не мучайтесь и перед использованием сравнения просто выведите на экран то, что сравниваете. И все станет ясно.
Человек '\n' не увидит и не поймет в чем дело
0
Эксперт С++
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
04.08.2011, 17:39 10
Цитата Сообщение от Olga_ Посмотреть сообщение
Человек '\n' не увидит и не поймет в чем дело
Угу. Поэтому я строки при проверке всегда в кавычках или в скобках вывожу.
0
Заблокирован
04.08.2011, 17:39 11
Цитата Сообщение от Olga_ Посмотреть сообщение
Да, и это тоже конечно, что-то я упустила этот момент, спасибо

Добавлено через 1 минуту


Человек '\n' не увидит и не поймет в чем дело
Все он увидит! Достаточно просто написать

C++
1
printf( "[%s]\n", s );
или

C++
1
printf( "\"%s\"\n", s );
То есть заключить строку в любые ограничители.
0
Эксперт С++
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
04.08.2011, 17:41 12
Цитата Сообщение от Сыроежка Посмотреть сообщение
Все он увидит! Достаточно просто написать
Для этого нужен опыт. Но вряд ли вопрос бы тогда появился
0
848 / 190 / 18
Регистрация: 01.08.2011
Сообщений: 505
04.08.2011, 17:41 13
Цитата Сообщение от grizlik78 Посмотреть сообщение
Угу. Поэтому я строки при проверке всегда в кавычках или в скобках вывожу.
Все правильно, только вот человек боится параметры strtok() менять, мусором это называет, ему так скажите
0
307 / 20 / 4
Регистрация: 01.05.2010
Сообщений: 250
04.08.2011, 17:47  [ТС] 14
-=ЮрА=-, разобрался.

Цитата Сообщение от Olga_ Посмотреть сообщение
Все правильно, только вот человек боится параметры strtok() менять, мусором это называет, ему так скажите
А что это, если не мусор? Если бы мне нужно было делить строку по пробелам И точкам, я бы добавил пробел. Но зачем мне лишние разделители? Я еще раз спрашиваю, strtok() не работает с одним разделителем? аргументируйте, коль крикнули.

Всем спасибо.
0
848 / 190 / 18
Регистрация: 01.08.2011
Сообщений: 505
04.08.2011, 17:50 15
Цитата Сообщение от AK3RN Посмотреть сообщение
-=ЮрА=-, разобрался.



А что это, если не мусор? Если бы мне нужно было делить строку по пробелам И точкам, я бы добавил пробел. Но зачем мне лишние разделители? Я еще раз спрашиваю, strtok() не работает с одним разделителем? аргументируйте, коль крикнули.

Всем спасибо.
Пост 6 прочитайте еще раз, там пример. Если у вас функция fgets(), то как минимум '\n' надо добавить в strtiok().
0
307 / 20 / 4
Регистрация: 01.05.2010
Сообщений: 250
04.08.2011, 17:56  [ТС] 16
Цитата Сообщение от Olga_ Посмотреть сообщение
Пост 6 прочитайте еще раз, там пример. Если у вас функция fgets(), то как минимум '\n' надо добавить в strtiok().
Спасибо за уточнение.
0
935 / 760 / 299
Регистрация: 09.12.2010
Сообщений: 1,346
Записей в блоге: 1
04.08.2011, 18:05 17
Зачем постояно токенировать строку если можно первые N = strlen(name) символы сравнивать, вот пример кода, поиск по-фамилии без учёта регистра.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdio.h>
#include <string.h>
#include <ctype.h>
 
const char*  is_name(const char* str, const char* name) {
   if(! strnicmp(name, str, strlen(name))) {
        if( isspace(*((str) + strlen(name))) )
            return  str + strlen(name);
   }
   return NULL;
}
 
 
int main(void) {
 
   char  line[255];
   char  name[32];
   const char* str;
   char* tok;
   FILE* fp;
 
   printf("input name: ");
   scanf("%s", name);
   fp = fopen("person.txt", "r");
 
   while(! feof(fp)) {
        fgets(line, sizeof(line), fp);
        if((str = is_name(line, name)) != NULL) {
            for(tok = strtok(str, " \t"); tok; tok = strtok(NULL, " \t"))
                puts(tok);
        }
   }
   fclose(fp);
 
   getch();
   return 0;
}
0
Заблокирован
04.08.2011, 18:10 18
ВЫ умудрились в одной маленькой функции вызвать strlen три раза для одной и той же константной строки!
0
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
05.08.2011, 04:36 19
Цитата Сообщение от Olga_
C
1
2
3
while(!feof(f))
        {
                fgets (str , 256 , f);
Цитата Сообщение от xAtom
C
1
2
while(! feof(fp)) {
        fgets(line, sizeof(line), fp);
неправильный подход
если будет ошибка чтения файла, цикл повиснет, потому что конец файла никогда не наступит

C
1
2
    while(fgets(line, sizeof(line), fp) != NULL)
        ;
1
kazak
05.08.2011, 04:53     Получить от пользователя фамилию и вывести из этого файла инициалы и год рождения этого человека
  #20

Не по теме:

-=ЮрА=-, правильно все таки будет

C++
1
char * str = new char[Len + 1];
accept, подход действительно неправильный, но если будет ошибка чтения файла, то EOF должен будет установиться в любом случае.

0
05.08.2011, 04:53
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
05.08.2011, 04:53
Помогаю со студенческими работами здесь

Описать тип-структуру «Человек», хранящую имя, фамилию и год рождения человека
Описать тип-структуру «Человек», хранящую имя, фамилию и год рождения человека. Описать функцию,...

Вывести фамилию, инициалы и высчитать возраст на текущий год
создать программу которая вводит строки содержащие фамилию,имя, отчество и год рождения. а выводит...

Вывести таблицей фамилию, год рождения, оценку за первую и вторую сессию
Здраствуйте, в програме нужно вывести таблицей с фамилию, год рожд, оценка за 1 сесию и вторую ...

Определить самого старшего человека из списка и вывести его фамилию, имя и дату рождения
Имеется список людей с указанием их фамилии, имени и даты рождения. Напишите эффективную по времени...

Вывести данные о студентах: номер, фамилию, год рождения, пол, курс, вид спорта
Доброго времени суток. Помогите с задачей. Составить программу, которая вводит данные о...

Известны год и номер месяца рождения человека, определить возраст человека
Известны год и номер месяца рождения человека, а также год и номер месяца сегодняшнего дня (январь...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru