Вывод строки из файла

Аватара пользователя

Автор темы
ValentO
Сообщения: 3
Зарегистрирован: 04 дек 2015, 15:01

Вывод строки из файла

#1

Сообщение ValentO » 04 дек 2015, 15:48

Здравствуйте форумчане.Я новичок,что в программировании,что в Linux-е. Задача такова,нужно вывести ФИО и его группу(в уже ранее созданном файле,структуру приведу ниже). То есть,должен использоваться ввод с клавиатуры,затем сравнение,если это ФИО в файле(если есть,то вывод ФИО и его группы), иначе такого ФИО не существует. Заранее спасибо. Если же кто поможет,то хоть немного прокомментируйте код.

Собственно сам список:
группа 1
Агапов Борис Николаевич
Агнивцев Николай Яковлевич
Бальмонт Константин Дмитриевич
Гофман Модест Людвигович
группа 2
Есенин Сергей Александрович
Маяковский Владимир Владимирович
Позняков Николай Сергеевич
группа 3
Цветаева Марина Ивановна
Иванов Георгий Владимирович
Бунин Иван Алексеевич


P.S Прошу прощение,если не ясно написал задание.Я тут что-то сделал,но это не внушает доверия.

Код: Выделить всё

#!/bin/bash

s1='vvod'
s2='string'
echo -n "Enter the data writer"

if [$s1=$s2];
  then
       echo" Tour search no results"
   fi
      if [$s1=$s1];
        then
            echo "Your results"
            fi
read vvod

echo "You entered: $s1"

grep -r $vvod spisok;

chmod a+x script.sh

Аватара пользователя

newerty
Сообщения: 282
Зарегистрирован: 11 окт 2015, 20:52

Re: Вывод строки из файла

#2

Сообщение newerty » 04 дек 2015, 16:10

Задача такова,нужно вывести ФИО и его группу

Объясните, нужно, чтобы по каким-либо введенным параметрам нашлась запись, как в базе данных (в нашем случае файл играет ее роль, я правильно понимаю)?
Можно допустим по ID найти ФИО и группу, по группе найти список участников, поясните свою цель, может быть, помогу.
Вы хотите просто по ФИО найти номер/код группы? Довольно нетрудно, в принципе.
Лучше всего написать на PHP+MySQL, было бы очень удобно, хотя можно и так в принципе.

Аватара пользователя

Автор темы
ValentO
Сообщения: 3
Зарегистрирован: 04 дек 2015, 15:01

Re: Вывод строки из файла

#3

Сообщение ValentO » 04 дек 2015, 19:06

newerty писал(а):
Задача такова,нужно вывести ФИО и его группу

Объясните, нужно, чтобы по каким-либо введенным параметрам нашлась запись, как в базе данных (в нашем случае файл играет ее роль, я правильно понимаю)?
Можно допустим по ID найти ФИО и группу, по группе найти список участников, поясните свою цель, может быть, помогу.
Вы хотите просто по ФИО найти номер/код группы? Довольно нетрудно, в принципе.
Лучше всего написать на PHP+MySQL, было бы очень удобно, хотя можно и так в принципе.

Скажу так,предположим я ввожу фамилию (Маяковский) и мне на основе найденных результатов,выводятся все найденные (Маяковский Владимир Владимирович группа 2),вот как-то так.Просто нужно именно на языке shell.

Аватара пользователя

newerty
Сообщения: 282
Зарегистрирован: 11 окт 2015, 20:52

Re: Вывод строки из файла

#4

Сообщение newerty » 04 дек 2015, 19:16

Ну, на shell не знаю как, я на си только могу.

Аватара пользователя

Автор темы
ValentO
Сообщения: 3
Зарегистрирован: 04 дек 2015, 15:01

Re: Вывод строки из файла

#5

Сообщение ValentO » 04 дек 2015, 19:18

newerty писал(а):Ну, на shell не знаю как, я на си только могу.

Если Вам,не сложно,напишите хоть на СИ,может я от Ваших полученных результатов,сам себя на мысль толкну.

Аватара пользователя

serg666
Сообщения: 604
Зарегистрирован: 26 фев 2013, 21:15

Re: Вывод строки из файла

#6

Сообщение serg666 » 04 дек 2015, 22:26

Код: Выделить всё

#!/bin/bash

INPUTFILE=./spisok.txt
GROUPNAME="группа"

WRITER=""
until [ "$WRITER" ]; do
   read -p "Enter the data writer: " WRITER
done

GROUP=""
AUTHOR=""
cat < $INPUTFILE | while read; do
   if `echo "$REPLY" | grep "$GROUPNAME" > /dev/null`; then
      GROUP="$REPLY";
   elif `echo "$REPLY" | grep "$WRITER" > /dev/null`; then
      echo $GROUP
      echo $REPLY
      AUTHOR=$REPLY
   fi
done
[ "$AUTHOR" ] || echo "Ничего не найдено"
Последний раз редактировалось serg666 05 дек 2015, 10:27, всего редактировалось 1 раз.

Аватара пользователя

newerty
Сообщения: 282
Зарегистрирован: 11 окт 2015, 20:52

Re: Вывод строки из файла

#7

Сообщение newerty » 05 дек 2015, 02:36

 base.txt
Агапов Борис Николаевич:1
Агнивцев Николай Яковлевич:1
Бальмонт Константин Дмитриевич:1
Гофман Модест Людвигович:1
Есенин Сергей Александрович:2
Маяковский Владимир Владимирович:2
Позняков Николай Сергеевич:2
Цветаева Марина Ивановна:3
Иванов Георгий Владимирович:3
Бунин Иван Алексеевич:3

 base.cpp

Код: Выделить всё

#include <fstream>
#include <iostream>
#include <cstring>

#define file "base.txt"

using namespace std;

int
strchrn(char *s, int c)
{
   int n = -1;
   while (*s)
   {
      n++;
      if (*s == c) return n;
      s++;
   }
   return -1;
}

int
strchrs(char *s, char *t)
{
   while (*t)
   {
      int r = strchrn(s, *t);
      if (r > -1) return r;
      t++;
   }
   return -1;
}

int
main(void)
{
   char buffer[1024], fio[50], groop[10];
   int count = 0, number;
   cout << "Введите ФИО или группу: ";
   cin.getline(fio, 50);
   ifstream input(file);
   while(input.getline(buffer, 1024))
   {
      if (strstr(buffer, fio))
      {
         count++;
         if (count == 1)
            cout << endl;
         number = strchrs(buffer, ":");
         strcpy(groop, &buffer[number+1]);
         buffer[number] = 0;
         cout << count << ": \t" << buffer << endl;
         cout << "\tГруппа: " << groop << endl;
      }
   }
   if (count == 0)
      cout << "\nНичего не найдено." << endl;
   else
      cout << "\nНайдено " << count << " записей в базе." << endl;
   return 0;
}

g++ base.cpp -o base -s
 Результат
Группа

Код: Выделить всё

Введите ФИО или группу: 2

1:    Есенин Сергей Александрович
   Группа: 2
2:    Маяковский Владимир Владимирович
   Группа: 2
3:    Позняков Николай Сергеевич
   Группа: 2

Найдено 3 записей в базе.

Имя

Код: Выделить всё

Введите ФИО или группу: Николай

1:    Агнивцев Николай Яковлевич
   Группа: 1
2:    Позняков Николай Сергеевич
   Группа: 2

Найдено 2 записей в базе.

Единственное - 49 строка что-то сказать пытается, но я не понимаю, что.
p.s. Ошибка устранена немного другим способом, меньше кода, все работает точно так же.
 Решение

Код: Выделить всё

#include <fstream>
#include <iostream>
#include <cstring>

#define file "base.txt"

using namespace std;

int
main(void)
{
   char buffer[1024], fio[50], groop[10], *sp;
   int count = 0, number, cnt;
   cout << "Введите ФИО или группу: ";
   cin.getline(fio, 50);
   ifstream input(file);
   while(input.getline(buffer, 1024))
   {
      if (strstr(buffer, fio))
      {
         count++;
         if (count == 1)
            cout << endl;
         sp = strtok(buffer, ":");
         cnt = 0;
         while (sp)
         {
            if (cnt == 0)
               cout << count << ": \t" << sp << endl;
            else
               cout << "\tГруппа: " << sp << endl;
            sp = strtok(NULL, ":");
            cnt++;
         }
      }
   }
   if (count == 0)
      cout << "\nНичего не найдено." << endl;
   else
      cout << "\nНайдено " << count << " записей в базе." << endl;
   return 0;
}

 С комментариями

Код: Выделить всё

// Заголовочные файлы
#include <fstream>
#include <iostream>
#include <cstring>

// Некоторые установки
#define FILE "base.txt" // Файл с базой об учащихся (в текущей папке или прямой путь к файлу)
#define BUFFER_SIZE 1024 // Размер буфера для строки
#define FIO_SIZE 50 // Максимальный размер ФИО

// Использование стандартных функций ввода и вывода в программе
using namespace std;

// Главная функция
int
main(void)
{
   // Объявление переменных
   char buffer[BUFFER_SIZE], fio[FIO_SIZE], *sp;
   int count = 0, number, cnt;

   // Запрос на ввод искомых данных
   cout << "Введите ФИО или группу: ";
   cin.getline(fio, FIO_SIZE);

   // Открываем поток с файлом
   ifstream input(FILE);

   // Построчно читаем данные из файла
   while(input.getline(buffer, BUFFER_SIZE))
   {
      // Если содержатся искомые данные
      if (strstr(buffer, fio))
      {
         // Увеличиваем счетчик
         count++;

         // Для более правильного вывода данных в консоль
         if (count == 1)
            cout << endl;

         // Разделяем в строке нужные нам поля (поле ФИО и группы)
         sp = strtok(buffer, ":");

         // Обнуляем счетчик полей в данной строке
         cnt = 0;

         // Выводим все поля (дальше будет некая хитрость)
         while (sp)
         {
            // Если счетчик равен нулю - выводим ФИО
            if (cnt == 0)
               cout << count << ": \t" << sp << endl;

            // Если счетчик равен одному - выводим группу
            else
               cout << "\tГруппа: " << sp << endl;

            // Разделитель полей
            sp = strtok(NULL, ":");

            // Увеличение счетчика полей
            cnt++;
         }
      }
   }

   // Выводим информацию о количестве найденных записей
   if (count == 0)
      cout << "\nНичего не найдено." << endl;
   else
      cout << "\nНайдено " << count << " записей в базе." << endl;
   return 0;
}

 Дополнение
Может еще пригодиться маленькая программа для конвертации списка с учащимися (сотрудниками, в зависимости от применения) и присвоение им всем одной группы, чтобы самому список не составлять, добавляя разделитель, а потом еще ко всем участникам группу. Короче, это все можно сделать мгновенно, а потом результат можно записать в нашу базу. Таким образом, у нас будет больше сведений.

Код: Выделить всё

#include <fstream>
#include <iostream>

#define INPUT      "input.txt" // Файл со списком людей, которых нужно приписать к группе
#define OUTPUT      "output.txt" // Выходной файл
#define GROOP      "MY-GROOP" // Группа, к которой мы приписываем людей
#define SEPARATOR   ":" // Разделитель между полями
#define BUF_SIZE   1024 // Размер буфера

using namespace std;

int
main(int argc, char* argv[])
{
   char buffer[BUF_SIZE]; // Переменная для буфера
   const char *groop; // Группа
   int str = 0, count = 0; // Количество строк в файле
   if (argc > 1)
      groop = argv[1];
   else
      groop = GROOP;
   ifstream col;
   col.open(INPUT);
   while( !col.eof())
      if(col.get() == '\n')
         str++;
   str++;
   col.close();
   ofstream F;
   F.open(OUTPUT);
   ifstream input(INPUT);
   while(input.getline(buffer, BUF_SIZE))
   {
      if (count+1 != str)
         F << buffer << ":" << groop << "\n";
      else
         F << buffer << ":" << groop;
      count++;
   }
   F.close();
   return 0;
}

Пример работы
Входные данные:

Код: Выделить всё

Имя1 Фамилия1 Отчество1
Имя2 Фамилия2 Отчество2
Имя3 Фамилия3 Отчество3
Имя4 Фамилия4 Отчество4
Имя5 Фамилия5 Отчество5
Имя6 Фамилия6 Отчество6

Выходные данные:

Код: Выделить всё

Имя1 Фамилия1 Отчество1:БИ-238
Имя2 Фамилия2 Отчество2:БИ-238
Имя3 Фамилия3 Отчество3:БИ-238
Имя4 Фамилия4 Отчество4:БИ-238
Имя5 Фамилия5 Отчество5:БИ-238
Имя6 Фамилия6 Отчество6:БИ-238

Запускаем:
./convert БИ-238
Добавляем в нашу базу какие-то новые данные:
cat output.txt >> base.txt
Очищаем входные данные после работы:
rm input.txt && touch input.txt

 Рациональная нагрузка процессора
Чтобы во время работы этой программы можно было заняться чем-то другим, нужно рационализировать расходы процессора, пусть тогда и будет дольше выполняться программа, однако может тоже пригодиться. Расходуется примерно 1% процессора. Немного изменил код, теперь также выводится строка, где найдено совпадение.

Код: Выделить всё

#include <fstream>
#include <iostream>
#include <cstring>
#include <time.h>

#define FILE      "big.txt" // Файл с данными
#define SLEEP   20000000 // Время сна, в итоге не нагружается процессор
#define FIO      10 // Размер ФИО, будут искаться 9 введенных символов
#define BUFFER   100 // Размер буфера, это 50 символов на строку в линуксе, всегда можно сделать каким угодно

using namespace std;

int
main(void)
{
   timespec sleep = {0};
   sleep.tv_nsec = SLEEP;
   char buffer[BUFFER], fio[FIO], *sp;
   int count = 0, number, cnt, line = 0;
   cout << "Введите ФИО или группу: ";
   cin.getline(fio, FIO);
   ifstream input(FILE);
   while(input.getline(buffer, BUFFER))
   {
      line++;
      if (strstr(buffer, fio))
      {
         count++;
         if (count == 1)
            cout << endl;
         sp = strtok(buffer, ":");
         cnt = 0;
         while (sp)
         {
            if (cnt == 0)
               cout << count << ": \t" << sp << endl;
            else
               cout << "\tГруппа: " << sp << endl << "\tСтрока: " << line << endl;
            sp = strtok(NULL, ":");
            cnt++;
         }
      }
      nanosleep(&sleep, NULL);
   }
   if (count == 0)
      cout << "\nНичего не найдено по запросу '" << fio << "'." << endl;
   else
      cout << "\nНайдено " << count << " записей в базе." << endl;
   return 0;
}
Последний раз редактировалось newerty 06 дек 2015, 09:43, всего редактировалось 6 раз.


azmcrum
Сообщения: 75
Зарегистрирован: 12 авг 2015, 02:33

Re: Вывод строки из файла

#8

Сообщение azmcrum » 05 дек 2015, 14:48

Вот на баше:

Код: Выделить всё

#!/bin/bash

# Файл с именами
BASE_FILE="spisok.txt"
# Слово разделяющие группы строк (без индекса)
GROUP_NAME="группа"

LAST_LINE_N=$(cat "$BASE_FILE" | wc -l)
GROUPS_AR=($(grep -n "$GROUP_NAME" "$BASE_FILE" | sed 's/:.*$//'))
ALL_GROUPS_N=${#GROUPS_AR[*]}
GROUPS_AR[ALL_GROUPS_N]=$LAST_LINE_N

Input_name() {
read -p "Введите ФИО: " FIND_NAME
[ -z "$FIND_NAME" ] && Input_name
FIND_STRINGS="$(grep -n "$FIND_NAME" "$BASE_FILE" | sed 's/:.*$//')"
[ -z "$FIND_STRINGS" ] && { echo -e "Не найдено.\n"; Input_name; }
}
Input_name

for STR in $FIND_STRINGS; do
   while [ "$ALL_GROUPS_N" -gt ${N:-0} ]; do
      GROUP1="${GROUPS_AR[N]}"
      let N+=1
      GROUP2="${GROUPS_AR[N]}"
      [ "$GROUP1" -lt "$STR" ] && [ "$GROUP2" -ge "$STR" ] && { GROUP="$(sed -n ""$GROUP1"p" "$BASE_FILE")"; break; }
   done
   FIO="$(sed -n ""$STR"p" "$BASE_FILE")"
   echo -e "\n$GROUP\nФИО: $FIO\n"
done



serg666,
вообще не то.

Аватара пользователя

serg666
Сообщения: 604
Зарегистрирован: 26 фев 2013, 21:15

Re: Вывод строки из файла

#9

Сообщение serg666 » 05 дек 2015, 15:24

Да ладно не то, мелкая ошибка не влияющая на работоспособность, это да.
Исправленная версия:

Код: Выделить всё

#!/bin/bash

INPUTFILE=./spisok.txt
GROUPNAME="группа"

WRITER=""
until [ "$WRITER" ]; do
   read -p "Enter the data writer: " WRITER
done

GROUP=""
FLAG=""
while read REPLY; do
   if `echo "$REPLY" | grep "$GROUPNAME" > /dev/null`; then
      GROUP="$REPLY";
   elif `echo "$REPLY" | grep "$WRITER" > /dev/null`; then
      echo $GROUP
      echo $REPLY
      FLAG=1
   fi
done < $INPUTFILE
[ "$FLAG" ] || echo "Ничего не найдено"

Вдобавок мой скрипт работает не только в баше любой версии, но даже и в самом простом шелле /bin/sh


azmcrum
Сообщения: 75
Зарегистрирован: 12 авг 2015, 02:33

Re: Вывод строки из файла

#10

Сообщение azmcrum » 06 дек 2015, 00:39

версия 3.0:

Код: Выделить всё

#!/bin/sh

INPUTFILE="./spisok.txt"
GROUPNAME="группа"

until [ "$WRITER" ]; do read -p "Enter the data writer: " WRITER; done

while read LINE; do
   N=$((N+=1))
   echo "$LINE" | grep -q "$GROUPNAME" && { GROUP="$LINE"; continue; }
   echo "$LINE" | grep -q "$WRITER" && { printf "\n$GROUP\ncтрока $N: $LINE\n\n"; FLAG=1; }
done < $INPUTFILE

[ "$FLAG" ] || echo "Ничего не найдено."


Но этот скрипт обрабатывает кажую строку в цикле,
что может заметно загрузить ЦП если строк будет много.
А в моей версии для поиска фио grep читает список только
один раз, и потом обрабатываются только номера строк (поиск группы).
Хотя это все можно сделать в "пару строк" на sed'е
и производительность тогда будет намного выше.
Все таки лучше использовать нормальные СУБД.


Вернуться в «Разработка и тестирование»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость