Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 23, средняя оценка - 4.65
hom9k
Сообщений: n/a
#1

Потеря символа при копировании строки - C++

19.04.2009, 15:47. Просмотров 2781. Ответов 18
Метки нет (Все метки)

По условию задано количество символов n и текстовый файл. Если длина строки в файле больше n, то ее нужно разбить (оставить n символов на строке, а остаток на новую), там же где количество символов меньше n, то файл нужно дополнить знаками "!". Результат сохранить как f2.txt. В принципе большая часть программы сделана, но есть проблемы с копированием со строки на строку(всегда теряются символы).

Вот кусочек программы...

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
sozdanie()
{
 FILE *f1;
 FILE *f2;
 char a[15],b[1];
 int i,p,n,qw=0;
 printf ("введите количество символов, n=");
 cin>>n;
 cout<<endl;
 printf ("при вводе, в конце каждой строки нажмите Enter;\n");
 printf ("в конце файла введите точку и нажмите клавишу Enter;\n");
 printf ("исходный файл f1:\n");
 f1=fopen ("a:f.txt", "w");
 gets (a);
 p=strlen (a);
 while (a[p-1]!='.')
    {
    if (n<p)
        {
        qw=p/n;
        for (i=1;i<=qw;i++)
            {
            char rab [20];
            strcpy (rab,a+i*n);
            a[i*n]='\n';
            strcpy (a+i*n+1,rab);
            }
        }
    fputs (a,f1);
    gets (a);
    fprintf (f1,"\n");
    p=strlen (a);
    }
  if (n<p)
    {
    qw=p/n;
    for (i=1;i<=qw;i++)
        {
        char rab [20];
        strcpy (rab,a+i*n);
        a[i*n]='\n';
        strcpy (a+i*n+1,rab);
        }
     }
  a[p-1]='\0';
  fputs (a,f1);
  fclose (f1);
  printf ("\n");
  printf ("===============\n");
  f2=fopen ("a:f2.txt","w");
  f1=fopen ("a:f.txt","r");
  while (!feof (f1))
    {
    fscanf (f1,"%s",&a);
    puts (a);
    fprintf (f2,"\n");
    fputs (a,f2);
    p=strlen (a);
    for (i=0;i<(n-p);i++)
        fprintf (f2,"%s","!");
    }
    fclose (f1);
    fclose (f2);
    printf ("\n");
    f2=fopen ("a:f2.txt", "r");
    printf ("файл f2:\n");
    cout<<"===================="<<endl;
    while (!feof(f2))
        {
        fscanf (f2,"%s",a);
        puts (a);
        }
    fclose (f2);
    printf ("конец!\n");
    while (!kbhit());
    menu();
Добавлено через 13 минут 53 секунды
Подскажите где ошибка и где нужно исправить? А то я голову сломал
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.04.2009, 15:47     Потеря символа при копировании строки
Посмотрите здесь:
Лишние символы в конце строки при копировании C++
Ошибка при копировании строки в конец файла C++
C++ Ошибка при чтении символа строки
C++ Ошибка при взятии символа под номером Х из строки
C++ Как задать конец строки и прекратить при вводе определённого символа?
Создать строку: с начало три символа первой строки, потом эти же три символа в обратном порядке C++
C++ Копирование из строки от символа до символа
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
accept
4821 / 3241 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
19.04.2009, 15:49     Потеря символа при копировании строки #2
C
1
2
3
4
5
    while (!feof(f1)) {
        fscanf(f1, "%s", &a);
        puts(a);
        fprintf(f2, "\n");
        fputs(a, f2);
fscanf(f1, "%s", &a); знаешь как работает ?
перед %s все пробельные символы съедает (шесть " \t\n\r\v\f")
про fgets не знаешь ?
C
1
2
    if ((p = fgets(line, MAXLINE, ifp)) != NULL)
        ;
лучше сначала получить строку из файла, а потом её обрабатывать (делить или дополнять), учитывать, что поделённая строка снова должна участовать в процессе, на следующем чтении
Evg
Эксперт CАвтор FAQ
17548 / 5786 / 370
Регистрация: 30.03.2009
Сообщений: 15,937
Записей в блоге: 26
19.04.2009, 15:57     Потеря символа при копировании строки #3
С начала же программы увидел косяк: gets - опасная функция. У неё нет никакой возможности задать хоть как-то размер буффера. Т.е. ты в неё подаёшь указатель на буффер длиной в 15 символов, но ввести можешь 100 символов, после чего у тебя память засрётся непредсказуемым образом. Поэтому как минимум буффер a надо увеличить до размера максимально допустимой длины строки при вводе с клавиатуры (влепи 1000, хуже не станет)

Ну и очевидный косяки наверное видишь сам - у тебя дублирование кода в цикле и за пределами цикла (для последней итерации). Данный вопрос я так понимаю, рассматривать пока не стОит.

Насколько я понимаю, ты сначала данные вводишь с клавиатуры, а потом загоняешь их в файл, при этом попутно делаешь разбивку длинных строк. Потом из этого файла перегоняешь в результирующий файл с заполнением остатка знаками "!"

В логику того, как ты написал, вникнуть сложно, но, подозреваю, что проблема у тебя в strcpy. Эта функция копирует до тех пор, пока не встретился нулевой байт. Т.е давай посмотрим строки 23 и 24. У тебя выделен буффер rab размером в 20 байт. Далее ты в него копируешь a+i*n. Теперь представь себе, что в a у тебя записано 200 байт, а n=10. В этом случае будет копирование начиная с 10 байта и до конца строки. Но тебе нужно скопировать только n байт. В этом случае обрати внимание на функцию strncpy. И учти, что нолик на конце придётся лепить ручками, т.к. при ограниченном копировании нолик не лепится

Добавлено через 1 минуту 48 секунд
Цитата Сообщение от accept Посмотреть сообщение
лучше сначала получить строку из файла, а потом её обрабатывать (делить или дополнять), учитывать, что поделённая строка снова должна участовать в процессе, на следующем чтении
А я бы из файла в файл перегонял побайтово. Читаю байт, если это не энтер, записываю его в результирующий файл. Если уже записано n символов, то записываю перевод строки. Если прочитал энтер, то по количеству текущих символов можно подсчитать, чколько знаков "!" нужно записать в файл и т.п.
hom9k
Сообщений: n/a
19.04.2009, 16:03     Потеря символа при копировании строки #4
Цитата Сообщение от Evg Посмотреть сообщение
Поэтому как минимум буффер a надо увеличить до размера максимально допустимой длины строки при вводе с клавиатуры (влепи 1000, хуже не станет)
Хорошо влеплю

Насколько я понимаю, ты сначала данные вводишь с клавиатуры, а потом загоняешь их в файл, при этом попутно делаешь разбивку длинных строк. Потом из этого файла перегоняешь в результирующий файл с заполнением остатка знаками "!"
Да...


А я бы из файла в файл перегонял побайтово. Читаю байт, если это не энтер, записываю его в результирующий файл. Если уже записано n символов, то записываю перевод строки. Если прочитал энтер, то по количеству текущих символов можно подсчитать, чколько знаков "!" нужно записать в файл и т.п.
Чувствую, что так и буду делать... Спасибо. Просто думал, что можно как-то из этой ерунды, которую я написал слепить что -нибудь...
Evg
Эксперт CАвтор FAQ
17548 / 5786 / 370
Регистрация: 30.03.2009
Сообщений: 15,937
Записей в блоге: 26
19.04.2009, 16:10     Потеря символа при копировании строки #5
Цитата Сообщение от hom9k Посмотреть сообщение
Чувствую, что так и буду делать... Спасибо. Просто думал, что можно как-то из этой ерунды, которую я написал слепить что -нибудь...
Слепить можно. Но ты правильно назвал это "ерундой" и после лепки и вправду получится скорее "что-то" нежили что-то работающее. Хотя если ты в жизни собираешься заняться программированием, то мой тебе совет: попробуй для начала из этой ерунды получить работающую программу. А потом сделай побайтово. Просто отрицательный опыт - это тоже очень полезный опыт. В данном случае ты возможно поймёшь, как НЕ надо делать, а это тоже много стОит
accept
4821 / 3241 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
20.04.2009, 00:06     Потеря символа при копировании строки #6
Цитата Сообщение от accept
лучше сначала получить строку из файла, а потом её обрабатывать (делить или дополнять), учитывать, что поделённая строка снова должна участовать в процессе, на следующем чтении
Цитата Сообщение от Evg
А я бы из файла в файл перегонял побайтово. Читаю байт, если это не энтер, записываю его в результирующий файл. Если уже записано n символов, то записываю перевод строки. Если прочитал энтер, то по количеству текущих символов можно подсчитать, чколько знаков "!" нужно записать в файл и т.п.
понимаешь, плюс строки в том, что по ней можно лазить как влево, так и вправо, при этом не трогая файл
представь мы разрезали строку, потому что она слишком длинная и формируем новую из этого обрезка и новой прочитанной - мы получаем, что-то вроде "one two\r\nthree four five\r\n", мы легко можем её переделать в "one two three four five" или без пробела между two и three (это зависит от нас, а не от того, что там в файле)
когда у тебя есть строка, с ней можно много что делать, в отличие от того, когда у тебя есть один символ (захочу слова переставлю в обратном порядке, а с символами ?)
просто, раз текст состоит из строк, прямо так и сказано, то и работать можно прямо со строками (сравни, поступила новая часть задания: проставить номеры перед строками; а у тебя твой побайтовый код написан, как ты будешь ставить номер перед первой строкой ? вот я, перед выводом её, просто поставлю номер, либо вставлю его прямо в строку (это тоже на нашё усмотрение, мне программа или файл не говорит, как и что мне делать), а у тебя - вот код вот так написан и всё - либо переписывать его весь, либо начинать дубликаты лепить (для первой строки одно писать для других - другое, но то же самое)
понимаешь, вот эта работа с файлом, она монолитная, он прогу напишет, сдаст и выкинет (я писал такие, они мне нигде не пригодились - просто куча прог, которые все работают, и которые нафиг не нужны), а вот когда делишь на маленькие части, тогда и переносить их в другие программы можешь (прямо строить другую программу из функций, которые ты написал несколько недель назад, вообще никак их не меняя)
знаешь, как легко, когда полпрограммы у тебя уже написано тобою же
Evg
Эксперт CАвтор FAQ
17548 / 5786 / 370
Регистрация: 30.03.2009
Сообщений: 15,937
Записей в блоге: 26
20.04.2009, 20:30     Потеря символа при копировании строки #7
> понимаешь, плюс строки в том, что по ней можно лазить как влево, так и вправо, при этом не трогая файл

Но в "обычных" случаях нет небоходимости лазить по строке
А в тех случаях, когда это надо, обычно чтение всё равно делают побайтово, формируя при этом строку, потому что в общем-то нет нормальных интерфесных функций, которые нормально бы работали со строкой (вариант Си++ не рассматриваю, потому что там понятие строки несколько больше, чем просто массив char'ов). При испольовании всех этих fget, fscanf и т.п. у тебя нет гарантии, что ты заранее влезешь в размер буффера (т.е. кто тебе сказал, что в файле тебе не попадётся строка длиной в миллион символов). А потому так или иначе на низком уровне всегда идёт побайтовое чтение (в том сичле и в вышеупомянутых интерфесах си++), а дальше уже зависит от задачи - нужно, формируй строки, нужно, формируй слова (токены), нужно - сразу на ходу делай промежуточное представление, заменяя ключевые слова на целочисленные значения и т.п. Но работая с файлом сразуже построково на Си ты наживёшь себе большой геморрой
accept
4821 / 3241 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
21.04.2009, 02:17     Потеря символа при копировании строки #8
Цитата Сообщение от Evg
Но в "обычных" случаях нет небоходимости лазить по строке
так я тебе привёл пример с номером строки, случай обычный

Цитата Сообщение от Evg
обычно чтение всё равно делают побайтово, формируя при этом строку
стандартные функции обеспечивают переносимость, зачем делать функцию, которая уже есть в стандарте ?

Цитата Сообщение от Evg
что ты заранее влезешь в размер буффера
fgets содержит буфер, он ограничивает количество введённых символов вплоть до нуль-символа, то есть задав 1000 у тебя максимум будет 999+нуль-символ, а минимум - \n

Цитата Сообщение от Evg
строка длиной в миллион символов
и она с тем же успехом может читать в память, которая может быть больше миллиона

Цитата Сообщение от Evg
на низком уровне всегда идёт побайтовое чтение
на низком уровне вообще инструкции и что

Цитата Сообщение от Evg
Но работая с файлом сразуже построково на Си ты наживёшь себе большой геморрой
наоборот, работая с файлом построково, ты создаёшь себе интерфейс, который более удобен для последующего включения этих методов в остальные программы и упрощает доработку, так как, спустя пару месяцев, не надо сидеть и разбираться в коде несколько часов, чтобы понять как он работает
если ты работаешь со строками, у тебя есть функции для строк, а если с токенами, у тебя есть функции для токенов, а те, которых нет, ты пишешь тут же и они у тебя будут на завтра готовы
я много разных программ собрал на одних и тех же функциях, многие функции я потом закидываю сюда (то есть мне не надо их сидеть тут и набирать, они у меня уже лежат в готовом виде)
ты думаешь, я не могу от них отказаться и перейти на другие ?
да я их перевожу даже в скрипты для линя, просто построчно переписывая их туда, а php, а javascript ? знаёшь сколько функций будут работать там точно так же как в C ? только там мне файлы открывать не надо, потому что они отделены от файлов
Evg
Эксперт CАвтор FAQ
17548 / 5786 / 370
Регистрация: 30.03.2009
Сообщений: 15,937
Записей в блоге: 26
21.04.2009, 10:30     Потеря символа при копировании строки #9
accept, я отвечу на поставленные тобой выше вопросы. Но для начала давай определимся, что мы под строкой подразумеваем. А то есть подозрение, что мы говорим немного о разном. Говоря о строке, я имел ввиду то, понятие, которое мы видим, открыв файл в строковом редакторе - т.е. фактически текст до энтера. В приведённом тобой выше примере про "one two\r\nthree four five\r\n" мне, как кажется, ты имеешь в виду всё-таки строковой бкффер, в который ты загоняешь какую-то часть файла. В кратце поясни, что ты имеешь ввиду под строкой. Ибо спор наш, безусловно, полезен для новичков, т.к. они увидят две точки зрения. Но, если мы будем говорить о разном, то попросту поставим их (новичков) в тупик
accept
4821 / 3241 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
21.04.2009, 13:01     Потеря символа при копировании строки #10
Цитата Сообщение от Evg
мне, как кажется, ты имеешь в виду всё-таки строковой бкффер
почему ты думаешь, что символы могут быть только буфером или только строкой ?
строка уже подразумевает символьный массив и, чтобы хранить её, без массива не обойтись, но строка имеет признак конца строки - нуль-символ
буфер - это символьный или не символьный массив, в данном случае символьный
мы можем прочитать строку в символьный массив и записать его в файл, а можем прочитать строку в символьный массив и записать её в файл
когда строка находится в символьном массиве, она там находится со своим концом в конце - нуль-символом, на него в последствии и будет реагировать функция вывода в файл

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* PrintLine: выводит строку l
              в файл ofp или в stdout, если NULL */
int PrintLine(const char *l, FILE *ofp)
{
    int res;
    
    if (l == NULL)
        return EOF;
    if (ofp == NULL)
        ofp = stdout;
    res = fprintf(ofp, "%s", l);
    return ferror(ofp) ?
               EOF : res;
}
но, пока она находится в массиве, мы можем им пользоваться, как буфером, достаточно задать ему размер, нужный для работы (чтобы при вставках не получить строку длиннее символьного массива); ну, я уже говорил что с ней можно делать - бери любую функцию и применяй, хоть полиндромы, хоть на токены раскладывай, хоть поиск проводи - всё, что нужно, для многих задач, там можно переставить слова местами, когда у тебя много функций, тебе остаётся только выбирать
когда мы закончили, мы имеем строку в символьном массиве, а буфер это не буфер (ну, пока мы с ней работали, это был буфер, а тут прекратили, стала просто строка в массиве)
и мы её

C
1
    PrintLine(line, ofp);
или на экран ещё, как у него там

C
1
2
    if (PrintLine(line, ofp) > 0)
        PrintLine(line, NULL);
http://dict.t-mm.ru/search?text=%E1%F3%F4%E5%F0
Evg
Эксперт CАвтор FAQ
17548 / 5786 / 370
Регистрация: 30.03.2009
Сообщений: 15,937
Записей в блоге: 26
21.04.2009, 20:26     Потеря символа при копировании строки #11
Ты меня не совсем понял. Я видимо не очень ясно выражаюсь. В общем никак не могу решить с чего начать, а потмоу возможно будет некий сумбур

Сначала касательно твоего примера. Массив char'ов (или указатель на char) ты трактуешь как string в понятии интерфейсов из string.h библиотеки libc: т.е. набор байтов, заканчивающихся нулём. Это всё прекрасно до тех пор, пока такая строка влезает в размер буффера (как изначально пытался сделать автор данной темы)

Проблема нашего с тобой спора изначально состоит в том, что хотелось бы работать с файлом таким образом, что читать оттуда строками (в вышеупомянутом понятии string). Но нормально сделать имея на руках лишь стандартные интерфейсы не получится. Немного отклонясь в сторону, скажу, что я несколько погорячился, сказав что все системные функции чтения строки из файл опасны - это не так, ибо в интерфейсе fgets действительно есть параметр, задающий размер буффера (таким образом данные мы не испортим). А вот gets является "опасной". Возвращаюсь к теме. Мы хотим читать построков из файла. Но интерфейсом fgets нормально ты этого не сделаешь, поскольку подавать в него ты должен буффер и размер, но при этом ты не знаешь заранее, какого размера буффер тебе нужно выделять, чтобы. Т.е. у тебя нет никакой гарантии, что fgets тебе прочтёт целую строку из файла, а потому по-хорошему ты должен писать свою процедуру, которая в цикле будет вызывать fgets и проверяя каждый раз, есть ли энтер в строке. Если нет, то тебе буффер надо удлинять и продолжать чтение до тех пор, пока ты не доехал до энтера. Только такой подход даёт тебе 100% гарантию, что ты будешь нормально построково читать файл. Ну и, как вариант, ты накладываешь техническое ограничение на максимальный размер строки в файле и работаешь в предположении соблюдения этого ограничения. Это тоже вариант, но годится он только для программ, написанных для себя. Для промышленных программных продуктов такое, понятное дело, не годится

> так я тебе привёл пример с номером строки, случай обычный
В случае, тобою описанном, я бы не заморачивался. Открываю файлы на чтение и на запись. В файл на запись пишу номер строки. Далее побайтово переписываю из файла чтения в файл записи до тех пор, пока не встречаю энтер. По энтеру в файл записи дополнительно пишу номер строки о опять всё повторяю. Ну и нужно ещё отсечь факт конца файла, чтобы не налепить лишний номер строки (которая окажется пустой)

> стандартные функции обеспечивают переносимость, зачем делать функцию, которая уже есть в стандарте ?
Выше в данном посте я тебе отписал пример работы с целиковой строкой. Стандартных функций на Си для этого нет. Для Си++ наверняка есть, но делают они то же, что я и описал - динамически довыделяют буффер до тех пор, пока недостигнем конца строки (энетра)

> fgets содержит буфер, он ограничивает количество введённых символов вплоть до нуль-символа, то есть задав 1000 у тебя максимум будет 999+нуль-символ, а минимум - \n
Замечание принимается. Выше я написал, что погорячился с этим утверждением. Однако для функции fscanf, которая использовалась в первоначальном посте, моё утверждение остаётся в силе

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

> на низком уровне вообще инструкции и что
Под фразой "на низком уровне" я подразумевал внутри библиотечных интерфейсов. С той точки зрения, что ты работаешь на высоком уровне с интерфейсами типа fgets, но их внутренняя реализация - это "низкий" уровень, который в общем случае на разных архитектурах реализуется по разному, а верхний уровень, как ты уже справедливо заметил, даёт нам возможность писать переносимые коды

Последний твой комментарий из поста #8 не совсем понял. И сдаётся мне, это всё по той же причине. Наверное мы говорим немного не об одном и том же
accept
4821 / 3241 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
23.04.2009, 03:28     Потеря символа при копировании строки #12
Цитата Сообщение от Evg
В случае, тобою описанном, я бы не заморачивался. Открываю файлы на чтение и на запись. В файл на запись пишу номер строки. Далее побайтово переписываю из файла чтения в файл записи до тех пор, пока не встречаю энтер. По энтеру в файл записи дополнительно пишу номер строки о опять всё повторяю. Ну и нужно ещё отсечь факт конца файла, чтобы не налепить лишний номер строки (которая окажется пустой)
в файл на запись ты пишешь номер строки
и
ты пишешь номер строки по ентеру

значит у тебя две ситуации, когда ты пишешь номер строки, а зачем нам две ситуации ?

у меня-то одна ситуация, если я прочитал строку
C
1
2
3
4
5
6
7
8
9
10
int ReadLine(char l[], unsigned maxlen, FILE *ifp)
{
    if (l == NULL || maxlen == 0)
        return EOF;
    if (ifp == NULL)
        ifp = stdin;
    if (fgets(l, maxlen, ifp) == NULL)
         return feof(ifp) ? 0 : EOF;
    return strlen(l);
}
то я знаю сколько символов в ней, если они в ней есть, я ставлю номер перед её выводом, а если их нет, то я не ставлю номер
тебе нужно обработать ситуацию когда файл закончился и ты её откладываешь на потом, а потом то уже сейчас наступило, вместо того, чтобы писать следующую часть программы, ты будешь думать потом, как обрабатывать конец файла (а ещё если и повсплывает там чего-нибудь в процессе, то ещё долго будешь сидеть и что-то там переделывать (я всё это знаю, потому что через всё это прошёл года полтора назад ))

Цитата Сообщение от Evg
Однако для функции fscanf, которая использовалась в первоначальном посте, моё утверждение остаётся в силе
я могу построить фукнцию и на основе fscanf, потому что в ней есть всё для ограничения ввода %999[^\n]%*с будет читать не более 999 символов до перевода строки, а сохранять при этом в итоге 999+нуль-символ или меньше+нуль-символ
а ещё, весь остальной код программы останется тем же самым, потому что изменение способа чтения проводится только в одной функции и, когда что-то всплывает, не нужно переписывать половину программы

Цитата Сообщение от Evg
а верхний уровень, как ты уже справедливо заметил, даёт нам возможность писать переносимые коды
переносимые коды - это ещё ерунда, главное что даёт верхний уровень - не нужно три часа сидеть и разбираться/вспоминать, в своей собственной же программе, в том, как она работает на большинстве своих участков, ты можешь потратить полчаса и тебе кажется, ну что тут такого, зато она вся такая простая, но это когда у тебя программа не больше листа, а когда у тебя проектик, в котором не одна такая программа а две, твои полчаса превратятся не в час, а в два (полчаса на одну, полчаса на другую, полчаса на то как они работают вместе и полчаса на то, а как дальше писать, чтобы всё не зашло в тупик в итоге), умножь это на количество модулей, которые ты будешь добавлять в неё (либо тебе придётся писать одну прогу три года, исключая все остальные, чтобы заниматься только ею, либо каждый раз начинать заново такое расследование)
ты не читал прогу на 1000 строк в одном файле ? напиши и почитай
у меня всё раскидано по нескольким файлам, чтобы тратить время на новый код и прогу, с которой я остановился неделю две назад я понимаю за 10 минут, остальные два часа я пишу для неё и интегрирую новое

Цитата Сообщение от Evg
Выделять каждый раз миллион байт, согласись, не кошерно
выделять каждый раз ?
буфер выделяется один раз, да и то, его можно высвободить и выделить заново второй раз, независимо от того, сколько раз в него будут записаны строки
например, работаем со словами, выделили буфер на 100, работаем со строками - на 1000, предполагаем, что строки будут большие выделили пару миллионов, ну, если больше, пишем для такой ситуации что сделать (для начала, запускаем функцию, в ней определяем действия - сообщение о слишком длинной строке и выход из программы)

Цитата Сообщение от Evg
Для Си++ наверняка есть, но делают они то же, что я и описал - динамически довыделяют буффер до тех пор, пока недостигнем конца строки (энетра)
ага, они будут выделять пока память не кончится, иначе что делать со строкой, которая будет длиннее доступной памяти
так вот, когда память кончится, а строка не кончится, что они будут делать ? как они её обработают дальше ? да никак, без дополнительных действий они просто должны сообщить вызывающей функции, чтобы это не затерялось в дебрях выполнения

Цитата Сообщение от Evg
Выше в данном посте я тебе отписал пример работы с целиковой строкой.
а я тебе написал, что читать можно прямо в память, которую можно перевыделить

Цитата Сообщение от Evg
А вот gets является "опасной". Возвращаюсь к теме. Мы хотим читать построков из файла. Но интерфейсом fgets нормально ты этого не сделаешь, поскольку подавать в него ты должен буффер и размер, но при этом ты не знаешь заранее, какого размера буффер тебе нужно выделять
вот для этого и существует динамическое выделение памяти
Evg
Эксперт CАвтор FAQ
17548 / 5786 / 370
Регистрация: 30.03.2009
Сообщений: 15,937
Записей в блоге: 26
23.04.2009, 21:32     Потеря символа при копировании строки #13
Очередной раз убеждаюсь, что мы с тобой друг друга не понимаем. Или понимаем, но плохо. Или плохо помним то, о чём писали раньше

Цитата Сообщение от accept Посмотреть сообщение
в файл на запись ты пишешь номер строки
и
ты пишешь номер строки по ентеру

значит у тебя две ситуации, когда ты пишешь номер строки, а зачем нам две ситуации ?
Зачем две ситуации. Всё это делается в цикле. Энтер - это конец цикла. Т.е. печать второго номера строки происходит уже в начале цикла

Цитата Сообщение от accept Посмотреть сообщение
тебе нужно обработать ситуацию когда файл закончился и ты её откладываешь на потом, а потом то уже сейчас наступило, вместо того, чтобы писать следующую часть программы...
Мысль слабо осилил, но конец файла тебе тоже нужно отрабатывать. В твоём случае это выливается в проверку результата твоей функции на ноль. Разницы никакой

Цитата Сообщение от accept Посмотреть сообщение
потому что через всё это прошёл года полтора назад ))
А я прошёл лет 12 назад

Цитата Сообщение от accept Посмотреть сообщение
я могу построить фукнцию и на основе fscanf, потому что в ней есть всё для ограничения ввода %999[^\n]%*с
Мой косяк. Совсем забыл про такое

Цитата Сообщение от accept Посмотреть сообщение
главное что даёт верхний уровень - не нужно три часа сидеть и разбираться/вспоминать, в своей собственной же программе, в том, как она работает на большинстве своих участков ....
Опять-таки не понимаю. Зачем мне 3 часа разбираться в том, что очень прозрачно. Написать одну процедуру и использовать её всегда - это правильно. Но универсальную процедуру на все случаи жизни не напишешь. Я предпочитаю под каждую задачу писать так, как для этой задачи ниболее просто

Цитата Сообщение от accept Посмотреть сообщение
ты не читал прогу на 1000 строк в одном файле ? напиши и почитай
Я писал проги, объем исходников которых переваливает за 100 мегабайт, а количество файлов переваливает за тысячи И такое пишется годами, а не часами

Цитата Сообщение от accept Посмотреть сообщение
буфер выделяется один раз, да и то, его можно высвободить и выделить заново второй раз, независимо от того, сколько раз в него будут записаны строки.....
Изначально у нас речь шла, как что-либо делать по-простому. Твоя идея была в том, что надо сразу читать строку целиком (в данном случае под строкой подразумевается последовательность символов, заканчивающихся энтером). Далее ты привёл код, который читает строку по кускам. Т.е. строку целиком ты всё-таки прочитать не можешь, а потому тебе приходится её обрабатывать по кускам. В этом месте возникает геморой (помнишь, ты ведь говорил, что нужно по строке бегать взад-вперёд сколько угодно)

Цитата Сообщение от accept Посмотреть сообщение
ага, они будут выделять пока память не кончится, иначе что делать со строкой, которая будет длиннее доступной памяти
Потому то я и говорю, что работать с целиковыми строками неправильно. Либо мы опять говорим о разных вещах

Добавлено через 4 минуты 7 секунд
Ну и собственно мой вариант печати файла с номерами строк

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
#include <stdio.h>
 
int
main (void)
{
  FILE *f;
  int c, line, need_line;
 
  f = fopen ("in.txt", "r");
 
  line = 1;
  need_line = 1;
  while ((c = fgetc (f)) != EOF)
    {
      if (need_line)
        {
          printf ("%d: ", line++);
          need_line = 0;
        }
 
      if (c == '\n')
        need_line = 1;
 
      printf ("%c", c);
    }
 
  fclose (f);
 
  return 0;
}
accept
4821 / 3241 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
24.04.2009, 08:40     Потеря символа при копировании строки #14
Цитата Сообщение от Evg
Зачем две ситуации. Всё это делается в цикле. Энтер - это конец цикла. Т.е. печать второго номера строки происходит уже в начале цикла
я думал ты с двумя сделаешь, у меня функция может посчитать длину строки после добавления в неё номера, а у тебя два printf вызова, я в итоге получу общий объём файла, а ты будешь думать, чем бы их объединить

Цитата Сообщение от Evg
Мысль слабо осилил, но конец файла тебе тоже нужно отрабатывать.
наверное ты перепродумал надо было тебе не говорить, тогда бы ты выложил код

Цитата Сообщение от Evg
А я прошёл лет 12 назад
ну, пройти можно по-разному

Цитата Сообщение от Evg
Мой косяк. Совсем забыл про такое
так ты и про fgets "забыл", поначалу не знал чем они с gets различаются

Цитата Сообщение от Evg
Зачем мне 3 часа разбираться в том, что очень прозрачно. Написать одну процедуру и использовать её всегда - это правильно. Но универсальную процедуру на все случаи жизни не напишешь.
прозрачно, это когда она практически нифига не делает - это прозрачно, а когда у тебя прога делает несколько больших работ, сидеть и разбираться в листинге, где какая проверка начинается, да так можно говорить, когда ты не писал прог
мне интересно читать не то, как она работает, а то, что она делает (а то, что оно написано надёжно, так я прошёл это ещё на начальном этапе, какие 100 мегабайт, ты вообще о чём ? )

Цитата Сообщение от Evg
Я писал проги, объем исходников которых переваливает за 100 мегабайт, а количество файлов переваливает за тысячи И такое пишется годами, а не часами
да нифига ты не писал, годами можно что угодно писать
можно goto в чужой проге поставить и сказать, что это ты писал её, ну типа часть, а потом всем рассказывать, что ты писал её всю, видал я таких, вон на хакере сидят (три строчки написать не в состоянии, зато понтов выше крыши)

Цитата Сообщение от Evg
Твоя идея была в том, что надо сразу читать строку целиком (в данном случае под строкой подразумевается последовательность символов, заканчивающихся энтером).
строка может не заканчиваться энтером, она может до конца файла идти, строка может быть длиннее буфера, предназначенного для неё и что ? если я захочу поставить начало в строке, я точно так же сделаю флажок, который проверит её концовку и вставлять номер буду по проверке
ты докажи, что мой способ плохой, геморрой ищешь - ну, найди и предъяви, а я посмотрю
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
24.04.2009, 09:14     Потеря символа при копировании строки
Еще ссылки по теме:
Потеря точности при масштабировании C++
Потеря значений переменных при расчетах C++
C++ Потеря точности при использовании static_cast
Ошибка доступа при копировании текстовых строк C++
C++ Как отцепить string от буфера при копировании

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

Или воспользуйтесь поиском по форуму:
Evg
Эксперт CАвтор FAQ
17548 / 5786 / 370
Регистрация: 30.03.2009
Сообщений: 15,937
Записей в блоге: 26
24.04.2009, 09:14     Потеря символа при копировании строки #15
Цитата Сообщение от accept Посмотреть сообщение
я думал ты с двумя сделаешь, у меня функция может посчитать длину строки после добавления в неё номера, а у тебя два printf вызова, я в итоге получу общий объём файла, а ты будешь думать, чем бы их объединить
Если "объём" - это размер исходного файла, то после второго printf'а ставляю строку count++; если размер результирующего, то добавляю инкрементацию после первого pintf

Цитата Сообщение от accept Посмотреть сообщение
так ты и про fgets "забыл", поначалу не знал чем они с gets различаются
Ни тем ни другим я никогда не пользовался. В исходнойм посте была программа с gets, я как-то подумал, что fgets - это то же самое, но с файлом. Не стал в man лезть

Цитата Сообщение от accept Посмотреть сообщение
да нифига ты не писал, годами можно что угодно писать
можно goto в чужой проге поставить и сказать, что это ты писал её, ну типа часть, а потом всем рассказывать, что ты писал её всю, видал я таких, вон на хакере сидят (три строчки написать не в состоянии, зато понтов выше крыши)
Когда нет доверия чужим словам, ты смысла в дальнейшем разговре на эту тему не вижу. Опускаться до того, чтобы что-то тебе доказывать не буду

Цитата Сообщение от accept Посмотреть сообщение
ты докажи, что мой способ плохой, геморрой ищешь - ну, найди и предъяви, а я посмотрю
Выложи исходник
Yandex
Объявления
24.04.2009, 09:14     Потеря символа при копировании строки
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru