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

Сосчитать количество строк в символьном массиве - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 12, средняя оценка - 4.75
Ёрик
46 / 46 / 2
Регистрация: 07.01.2009
Сообщений: 298
09.01.2009, 11:54     Сосчитать количество строк в символьном массиве #1
Есть у нас массив указателей(массив строк одномерный).Напр,

book, dog, mother,book, pistol,brother,dog

нужно вывести те элементы,которые встречаются более 1 раза.Выод будет таким:
book,dog
Как это сделать?Есть идея,чтобы создать новый двумерный массив указателей,в котором 1-ый индекс - это строка,а второй - число,которое показывает,сколько данная срока встречается раз.
Вот кусок программы(всю не буду показывать,только то,что интересует)
C++
1
2
3
4
5
6
char **s = (char**)malloc(N*sizeof(char*)); 
    for (i = 0; i <= N; i++)
    {
        *s = (char*)malloc(30*sizeof(char)); // 30  - это максимальный размер строки по условию
        gets(*s);
    }
Таким образом мы заносим строки в массив указателей(здесь все работает нормально).
Потом опять выделяем память под двумерный массив

C++
1
2
3
4
5
     char **cur = (char**)malloc(N*sizeof(char*));
    for  (i = 0; i < N; i++)
    {
        *cur = (char*)malloc(2*sizeof(char));
    }
И теперь нахождение одинаковых строк в массиве:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    for ( i = 0; i<N; i++)
    {
        int g = 0;
        for(j = i;j<N;j++)
        {
            if (strcmp(*s,cur[i][0])) == 0) //если i-ая строка в 1 массиве(**s) равна 1-ому индексу 2-го массива(там у нас хранятся строки)
            {
                *s++;// следующая строка массива (**s)
                cur[i][g++];// то увеличиваем 2-ой индекс,т.е. число повторяющихся строк
                break;
                
            }
            else 
            {
                strcpy(*s,cur[i][0]);// иначе копируется строка 1-го массива (**s) в массив cur(первый индекс)
                s++;
            }
        }
    }
Подскажите,алгоритм правильный?Если да,то у меня 100% ошибка в коде(не считает программа).А если можно сделать проще эту задачу,то напишите как.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.01.2009, 11:54     Сосчитать количество строк в символьном массиве
Посмотрите здесь:

C++ Найти количество слов в символьном массиве
C++ Проверка строк в двухмерном символьном массиве
Удалить начальные пробелы в !символьном массиве (типа char) C++
C++ Сосчитать и вывести количество различных чисел в массиве
C++ Количество цифр в массиве строк
C++ Найти в символьном массиве трёхзначные числа
Поиск числа в символьном массиве C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Mecid
 Аватар для Mecid
678 / 227 / 4
Регистрация: 15.10.2007
Сообщений: 1,247
09.01.2009, 13:19     Сосчитать количество строк в символьном массиве #2
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
int main(){
int idx[10];
char *mas[]={"mega","lomka","mega","toska","lomka"};
int i,j,l=0,n=0;
for(i=0;i<5;++i)
for(j=0;j<5;++j){
if(!strcmp(mas[i],mas[j]))
idx[n]=i;++n;}
for(i=0;i<n;++i)
printf("%s\n",mas[idx[i]]);
return 0;
}
не проверял,но алгоритм такой
Ёрик
46 / 46 / 2
Регистрация: 07.01.2009
Сообщений: 298
09.01.2009, 21:46  [ТС]     Сосчитать количество строк в символьном массиве #3
Цитата Сообщение от Mecid Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
int main(){
int idx[10];
char *mas[]={"mega","lomka","mega","toska","lomka"};
int i,j,l=0,n=0;
for(i=0;i<5;++i)
for(j=0;j<5;++j){
if(!strcmp(mas[i],mas[j]))
idx[n]=i;++n;}
for(i=0;i<n;++i)
printf("%s\n",mas[idx[i]]);
return 0;
}
не проверял,но алгоритм такой
Ошибка в строке
if(!strcmp(mas[i],mas[j]))
говорит,что 1 параметр can't convert from char to const char*

Добавлено через 18 минут 9 секунд
нашел на форуме,почему ошибка
Mecid
 Аватар для Mecid
678 / 227 / 4
Регистрация: 15.10.2007
Сообщений: 1,247
09.01.2009, 21:53     Сосчитать количество строк в символьном массиве #4
дай я тож почитаю
pavlinux
3 / 3 / 0
Регистрация: 09.01.2009
Сообщений: 41
09.01.2009, 22:02     Сосчитать количество строк в символьном массиве #5
Цитата Сообщение от Mecid Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <string.h>
 
int main() {
 
    int i, j, n = 0;
    int idx[25] = {0};
 
    char *mas[] = {"mega", "lomka", "mega", "toska", "lomka"};
 
    for (i = 0; i < 5; ++i) {
        for (j = 0; j < 5; ++j) {
            if (!strcmp(mas[i], mas[j]))
                idx[n] = i;
            ++n;
        }
    }
    for (i = 0; i < n; ++i)
        printf("%s\n", mas[idx[i]]);
    return 0;
}
не проверял,но алгоритм такой


5 * 5 будет 25, а не 10.

Добавлено через 4 минуты 58 секунд
Цитата Сообщение от Ёрик Посмотреть сообщение
Ошибка в строке
if(!strcmp(mas[i],mas[j]))
говорит,что 1 параметр can't convert from char to const char*

Добавлено через 18 минут 9 секунд
нашел на форуме,почему ошибка
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <string.h>
 
int main() {
 
    int i, j, n = 0;
    int idx[25] = {0};
 
    const char *mas[] = {"mega", "lomka", "mega", "toska", "lomka"};
 
    for (i = 0; i < 5; ++i) {
        for (j = 0; j < 5; ++j) {
            if (!strcmp(mas[i], mas[j]))
                idx[n] = i;
            ++n;
        }
    }
    for (i = 0; i < n; ++i)
        printf("%s\n", mas[idx[i]]);
    return 0;
}
Mecid
 Аватар для Mecid
678 / 227 / 4
Регистрация: 15.10.2007
Сообщений: 1,247
09.01.2009, 22:05     Сосчитать количество строк в символьном массиве #6
10 там условная все равно повтор эелементов меньше
pavlinux
3 / 3 / 0
Регистрация: 09.01.2009
Сообщений: 41
09.01.2009, 23:05     Сосчитать количество строк в символьном массиве #7
Цитата Сообщение от Mecid Посмотреть сообщение
10 там условная все равно повтор эелементов меньше


# for (i = 0; i < n; ++i)
# printf("%s\n", mas[idx[i]]);

Ну проверь, когда сюда 11 попадёт, и будет т.е. SIGFAULT
Ёрик
46 / 46 / 2
Регистрация: 07.01.2009
Сообщений: 298
10.01.2009, 21:15  [ТС]     Сосчитать количество строк в символьном массиве #8
Слушайте,у меня оказался неправильным ввод с клавиатуры.Помогите доделать!
C++
1
2
3
4
5
6
char **s = (char**)malloc(N*sizeof(char*));   
    for (i = 0; i <= N; i++)  
    {  
        *s = (char*)malloc(30*sizeof(char)); // 30  - это максимальный размер строки по условию  
        gets(*s);  
    }
эта часть неправильная
accept
4838 / 3237 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
11.01.2009, 00:50     Сосчитать количество строк в символьном массиве #9
вместо gets(*s)

Код
    fgets((*s)[i], 30-1, stdin);
gets пишет за пределы строки (сотрёт переменные или вызовы функций которые дальше идут, если ей передадут строку длиннее, чем может поместить символьный массив в который она записывает данные со станартного потока ввода)
fgets отличается тем что не стирает перевод строки у поступившей строки
pavlinux
3 / 3 / 0
Регистрация: 09.01.2009
Сообщений: 41
11.01.2009, 01:12     Сосчитать количество строк в символьном массиве #10
Цитата Сообщение от accept Посмотреть сообщение
вместо gets(*s)

Код
    fgets((*s)[i], 30-1, stdin);


Ага, щаз.... (*s)[i] - это int
gets пишет за пределы строки
(сотрёт переменные или вызовы функций которые дальше идут, если ей передадут строку длиннее, чем может поместить символьный массив в который она записывает данные со станартного потока ввода)
Не слушай бяку, плохого на советуют....

gets считает сколько сможет, зависит от операционки, а запишет,
именно сколько выделили malloc_ом, и всё равно её НЕХОРШО ИСПОЛЬЗОВАТЬ,
но по другим причинам.

C++
1
2
3
4
5
6
    char **s = (char**) malloc(n * sizeof (char *));
 
    for (i = 0; i < n; i++) {        
        *(s+i) = (char *) malloc(30*sizeof (char));
        fgets(*(s+i), 30, stdin);
    }


Добавлено через 2 минуты 27 секунд
Вот, проверяйте ...

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int main(void) {
 
    int i;
    int n = 6;
 
    char **s = (char**) malloc(n * sizeof (char *));
 
    for (i = 0; i < n; i++) {        
        *(s+i) = (char *) malloc(30*sizeof (char));
        fgets(*(s+i), 30, stdin);
    }
 
    for (i = 0; i < n; i++) {
        printf("%s\n", *s++);
        
    }
 
    free(*s);
    s = NULL;
    return (EXIT_SUCCESS);
}
accept
4838 / 3237 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
11.01.2009, 06:49     Сосчитать количество строк в символьном массиве #11
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
 
#include <stdio.h>
#include <stdlib.h>
 
#define MAXLINE  30   /* максимальная длина строки */
#define NLINES   3    /* максимальное количество строк */
 
/* выделяет память под строки и запрашивает для них ввод */
main()
{
    char **s;
    int i;
    
    if ((s = (char **) malloc(NLINES*sizeof(char *))) == NULL)
        return 1;
    for (i = 0; i < NLINES; i++) {
        if ((s[i] = (char *) malloc(MAXLINE*sizeof(char))) == NULL) {
            while (--i >= 0)
                free((void *) s[i]);
            free((void *) s);
            return 2;
        }    
        fgets(s[i], 30, stdin);
    } 
    
    /* gets(s[0]); */ /* раскомментируй и введи строку более 30 символов */
    
    for (i = 0; i < NLINES; i++) {
        printf("%s", s[i]);
        free((void *) s[i]);
    }
    free((void *) s);
    return 0;
}
pavlinux это чо такое

C++
1
    free(*s);
типа всё освобождение памяти ?

gets

Код
[guest@localhost tmp]$ cc test.c -o test
/tmp/ccGTx1aA.o: In function `main':
test.c:(.text+0xcd): warning: the `gets' function is dangerous and should not be used.
то есть в данном случае она стирает не переменные которые идут за строкой а заголовок следующего блока, а если это будет просто массив как раз за ним переменные и вызовы функций точно так же будут перезаписаны

на советуют пишется слитно
насчёт (*s)[i] мне показалось что он память правильно выделяет

Добавлено через 8 минут 29 секунд
C++
1
2
3
4
    for (i = 0; i < n; i++)
        printf("%s\n", *s++);  
  
    free(*s);
не заметил я прикола, так ты вообще память не освобождаешь
какой указатель она попробует освободить ? ты бы хоть запустил прогу свою
Ёрик
46 / 46 / 2
Регистрация: 07.01.2009
Сообщений: 298
11.01.2009, 12:12  [ТС]     Сосчитать количество строк в символьном массиве #12
полностью выкладываю сделанную задачу по условию,которое выложено в 1 сообщении
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define M 30
 
 
struct NUMB
{
    int numb;
    char name[30];
 
};
 
 
struct ITEM
{
    NUMB *numb;
    ITEM *next;
};
 
NUMB * makeNUMB(char *s)
{
        NUMB *numb=(NUMB*)malloc(sizeof(NUMB));
        strcpy(numb->name,s);
        numb->numb = 1;
        return numb;
}
 
ITEM *createList(NUMB *numb)
{
    ITEM *head=(ITEM*)malloc(sizeof(ITEM));
    head->numb = numb;
    head->next = NULL;
    return head;
}
 
void addItem(ITEM *head,NUMB *numb)
{
    while(head->next)
        head = head->next;
    head->next=(ITEM*)malloc(sizeof(ITEM));
    head->next->numb = numb;
    head->next->next = NULL;
}
 
 
NUMB * makeNumbADD(char *s,ITEM *head)
{
    NUMB *numb = (NUMB*)malloc(sizeof(NUMB));
    while(head)
    {
        if (strcmp(s,head->numb->name) == 0)
            head->numb->numb++;
        else
        {
            strcpy(head->numb->name,s);
            head->numb->numb = 1;
        }
        head = head->next;
    }
    return numb;
    
}
 
NUMB *ADD_THE_FIRST(char *s)
{
    NUMB *numb=(NUMB*)malloc(sizeof(NUMB));
    strcpy(numb->name,s);
    numb->numb = 1;
    return numb;
}
 
void printList(ITEM *head)
{
    while(head)
    {
        if (head->numb->numb > 1)
            printf("%s",head->numb->name);
        head = head->next;
    }
}
int main()
{
    unsigned int N;
    ITEM *head = NULL;
    
    int g = 0;
    
 
    scanf("%u",&N);
    char **s = (char**) malloc(N*sizeof(char*)); 
    char *last_name = (char*)malloc(N*sizeof(char)); 
      
 
    for (int i = 0; i < N; i++) 
    {          
        *(s+i) = (char *) malloc(30*sizeof(char));
        fflush(stdin);
        fgets(*(s+i), 30, stdin);  
    }
 
 
 
 
 
 
    for(int g = 0; g < N;g++)
    {
        if (g == 0)
        {
            head = createList(makeNUMB((*(s+g)))); 
            strcpy((last_name),(*(s + g)));
        }
        else
        {
            int count = 0;
            for(int j = 0; j < N;j++)
            {
                if (strcmp((last_name) , (*(s + g + j))) == 0)
                {
                    addItem(head, makeNumbADD(last_name,head));
                    strcpy((last_name),(*(s + g + j)));
                    count++;
                } // вот здесь access violation,возможно,выход за пределы массива,что только не делал,пробовал цикл до N - 1,1-ый раз проходит,а второй раз кбкаогда в этот цикл заходим,снова эта ошибка.Задачка видно очень легкая,только я устал все переписывать.Уже 8 часов без отрыва сижу и дебажу.В результате программа вообще изменилась до неузнаваемости.
                
            }
            if (count == 0)
            {
                char *temp = (char*) malloc(N*sizeof(char*));
                strcpy(temp,last_name);
                last_name = NULL;
 
                char *last_name = (char*)malloc(N*sizeof(char));
                strcpy(last_name,temp);
            }
        }
        (*(s+g))++;
    }
 
 
    printList(head);
    return 0;
}
Задумка: использовал список, каждым элементом
которого была струкура: строка длиной в 30 символов и целое
беззнаковое число (количество повторов).Бегу по исходному массиву и смотрю, есть ли текущая строка в списке (последовательным перебором с головы списка). Если нашел ее - увеличиваю счетчик у найденного элемента на единицу. Не
нашел (дошел до конца списка) - добавляю новый элемент со
счетчиком, равным единице.

Ну а после при простом проходе по списку вывожу только те
строки, у которых счетчик больше единицы.

Помогите доделать.Память не освобождал,т.к. в конце программы она сама освобождается принудительно(и писать не надо,я знаю как освобождать!!).

Добавлено через 4 минуты 31 секунду
Тут можно редактировать сообщения?не найду.Опять перед тем,как отдебажил программу, я вставлял defin'ы,и забыл обратно один define заменить(#define M 30),в результате 30 так и болтается по программе,ну это просто,думаю, недочет.
accept
4838 / 3237 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
11.01.2009, 13:33     Сосчитать количество строк в символьном массиве #13
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
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define asize(a)  (sizeof (a) / sizeof (a)[0])   /* вычисляет длину массива */
 
/* выводит элементы массива указателей на строки,
   которые встречаются более 1 раза */
main()
{
    char **l, *lines[] = {
        "book",
        "dog",
        "mother",
        "book",
        "pistol",
        "brother",
        "dog"
    };
    int i, j, n;
    
    if ((l = (char **) calloc(asize(lines), sizeof(char *))) == NULL)
        return 1;
    for (i = 0; i < asize(lines); i++)
        if ((l[i] = (char *) malloc(strlen(lines[i])+1)) == NULL) {
             while (--i >= 0)  
                 free((void *) l[i]);  
             free((void **) l);  
             return 2;
        } else
            strcpy(l[i], lines[i]);   /* копирует массив в память */
    for (i = 0, n = 0; i < asize(lines); n = 0, i++) {
        for (j = i+1; j < asize(lines); j++)
            if (*l[j] != '\0'
             && strcmp(l[i], l[j]) == 0 
             && n++
             && (*l[j] = '\0'))   /* если повтор встречается, он удаляется */
                ;
        if (n == 0)   /* оставляет только повторяющиеся строки */
            *l[i] = '\0';
    }
    for (i = 0; i < asize(lines); i++) {
        if (*l[i] != '\0')   /* выводит неудалённые строки */
            printf("%s\n", l[i]);
        free((void *) l[i]);   /* удаляет копии строк из памяти */
    }    
    free((void **) l);   /* удаляет указатель на массив копий из памяти */
    return 0;
}
Тут можно редактировать сообщения?
ага, только если залогинился
Ёрик
46 / 46 / 2
Регистрация: 07.01.2009
Сообщений: 298
11.01.2009, 14:03  [ТС]     Сосчитать количество строк в символьном массиве #14
accept,эта программа вообще не походит.Во-первых,нам не известно какие массивы будут(сроки) и их количество(их количество вводится вначале программы).И здесь полностью работа с динамическими массивами строк!!В результате от твоей программы ничего не остается.Мою версиб со списком может кто-л. проверить?Список он создает,но выскакивает ошибка,описанная выше.

Добавлено через 3 минуты 42 секунды
Кстати,вот(я залогинился):
Ваши права в разделе
Вы можете создавать темы
Вы можете отвечать на сообщения
Вы можете прикреплять файлы
Вы не можете редактировать сообщения (?)
accept
4838 / 3237 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
11.01.2009, 14:08     Сосчитать количество строк в символьном массиве #15
Во-первых,нам не известно какие массивы будут(сроки) и их количество(их количество вводится вначале программы).И здесь полностью работа с динамическими массивами строк!
можешь туда любые строки вписать прога работает с любыми строками, с любым количеством, предполагается пользователь ввёл строки дальше они идут на обработку
Ёрик
46 / 46 / 2
Регистрация: 07.01.2009
Сообщений: 298
11.01.2009, 16:33  [ТС]     Сосчитать количество строк в символьном массиве #16
понимаешь,вот смотри:размерость мы вводим вначале,поэтому
#define asize(a) (sizeof (a) / sizeof (a)[0]) убираем везде в программе(!)
и при динамическом распределении памяти мы не можем обратиться к символьному массиву s[i], а должны вот так: (s+i),при уловии,что мы создали указатель на указатель (для массива строк),в результате у нас **s массив строк,а указатель на первый элемент строк - *s,поэтому и от твоей программы почти ничего не осталось
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.01.2009, 17:16     Сосчитать количество строк в символьном массиве
Еще ссылки по теме:

C++ Подсчет количества пробелов в символьном массиве
C++ Проверить есть ли в символьном массиве нужный элемент?
C++ В символьном массиве заменить буквы на символ %
Продублировать в символьном массиве буквы кириллицы C++
C++ Вывод в символьном массиве в обратном порядке

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

Или воспользуйтесь поиском по форуму:
accept
4838 / 3237 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
11.01.2009, 17:16     Сосчитать количество строк в символьном массиве #17
когда у тебя **s, обращение к *s == *(s+0), а *(s+0) == s[0]
поэтому
*(s+1) == s[1]
*(s+2) == s[2]
и наоборот
s[3] == *(s+3)
s[4] == *(s+4)

вообще s[i] == *(s+i) и наоборот *(s+i) == s[i]

s == &s[0];

asize нужно заменить на количество строк в массиве, который пользователь закончил вводить
ты вроде про память писал что её освобождать не надо, это можно файлы не закрывать, а память надо освобождать
Yandex
Объявления
11.01.2009, 17:16     Сосчитать количество строк в символьном массиве
Ответ Создать тему
Опции темы

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