Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / В студии работает, а в консоли вылетает(Си) / 8 сообщений из 8, страница 1 из 1
03.12.2016, 19:08
    #39359900
vlladimir
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
В студии работает, а в консоли вылетает(Си)
Программа на Си для подсчета сколько раз каждое слово встречается в тексте, с использованием хештаблицы. Написана в VS 2013 при запуске локальным отладчиком работает, а при запуске из консоли вылетает.
hash.c
Код: plaintext
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.
#include "hashhead.h"

unsigned char hash(const char *str)
{
	unsigned int hash = 0;
	for (; *str; str++)
		hash = (hash * 1664525) + (unsigned char)(*str) + 1013904223;
	return hash>>24;
}
void insert(struct node *a[], char *word){
	unsigned char index;
	struct node *n, *p;
	p = findNode(word, a);
	if (p==NULL)
	{
		index = hash(word);
		n = (node*)malloc(sizeof(node*));
		strcpy_s(n->word,11, word);
		n->next = a[index];
		n->count = 1;
		a[index] = n;
	}
	else{
		p->count++;
	}
}

struct node *findNode(char *word, node* a[255]) {
	node *p;
	p = a[hash(word)];
	while (p && strcmp(p->word, word))
		p = p->next;
	return p;
}

void prntable(struct node *a[255]){
	int i;
	node *p;
	for (i = 0; i < 256; i++){
		p = a[i];
		while (p){
			printf("%s %d\n", p->word, p->count);
			p = p->next;
		}
	}
}

void prntable_f(struct node *a[255], FILE *f){
	int i;
	node *p;
	for (i = 0; i < 256; i++){
		p = a[i];
		while (p){
			fprintf(f,"%s %d\n", p->word, p->count);
			p = p->next;
		}
	}
}

int poscinstr(char *str, char c)
{
	unsigned int i;
	for (i = 0; i < strlen(str); i++){
		if (str[i] == c){
			return i;
		}
	}
	return -1;
}


hashhead.h
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
#ifndef HASHHEAD_H
#define HASHHEAD_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
void insert(struct node *a[], char *word);
unsigned char hash(const char *str);
void prntable(struct node *a[255]);
void prntable_f(struct node *a[255], FILE *f);
struct node *findNode(char *word, struct node *a[]);
typedef struct node
{
	char word[11];
	int count;
	struct node *next;
}node;

int poscinstr(char *str, char c);
#endif /*HASHHEAD_H*/


hashtest.c
Код: plaintext
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.
145.
146.
147.
148.
149.
150.
151.
#include "hashhead.h"

void main(int argc, char *argv[]) {

	node *a[256];
	FILE *f = stdout;
	FILE *fi = stdin;
	char str[2000];
	char word_t[50];
	char *estr, *letters, *symbols;
	unsigned int j;
	int k;
	letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
	for (j = 0; j < 256; j++){
		a[j] = (node*)malloc(sizeof(node*));
		a[j] = NULL;
	}
	switch (argc) {
	case 1:
		printf("hashtable, version 0.0.0.1 x86\n");
		printf("Usage: Input an text file\n");
		printf("hashtable.exe -in filename -o|-out filename\n");
		printf("Output: file containing amount of each word\n");
		break;
	case 2:
		if ((strcmp(argv[1], "-help") == 0) || (strcmp(argv[1], "-HELP") == 0)){
			printf("hashtable, version 0.0.0.1 x86\n");
			printf("Usage: Input an text file\n");
			printf("hashtable.exe -in filename -o|-out filename\n");
			printf("Output: file containing amount of each word\n");
			break;
		}
	case 3:
		if (strcmp(argv[1], "-in") == 0){
			if (fopen_s(&fi, argv[2], "r") == 0)
			{
				while (1){
					estr = fgets(str, 2000, fi);
					if (estr == NULL)
					{
						if (feof(fi) != 0)
						{
							fclose(fi);
							break;
						}
						else
						{
							printf("\nFile read error\n");
							break;
						}
					}
					j = 0;
					while ((poscinstr(letters, str[j]) <0) && (j < strlen(str))){
						j++;
					}
					k = 0;
					while (j < strlen(str)){
						word_t[k] = str[j];
						k++;
						j++;
						if (poscinstr(letters, str[j]) <0){
							word_t[k] = '\0';
							if ((strlen(word_t) < 11) && (strlen(word_t) > 0)) {
								insert(a, word_t);
							}
							k = 0;
							while ((poscinstr(letters, str[j]) <0) && (j < strlen(str))){
								j++;
							}
						}
					}
					word_t[k] = '\0';
					if ((strlen(word_t) < 11) && (strlen(word_t) > 0)) {
						insert(a, word_t);
					}
				}
				prntable(a);
				getchar();
				break;
			}
			else{
				printf("Input file not opened.");
				getchar();
				break;
			}
		}
	case 5:
		if ((strcmp(argv[1], "-in") == 0) && ((strcmp(argv[3], "-o") == 0) || (strcmp(argv[3], "-out") == 0))){
			if (fopen_s(&fi, argv[2], "r") == 0)
			{
				while (1){
					estr = fgets(str, 2000, fi);
					if (estr == NULL)
					{
						if (feof(fi) != 0)
						{
							fclose(fi);
							break;
						}
						else
						{
							printf("\nFile read error\n");
							break;
						}
					}
					j = 0;
					while ((poscinstr(letters, str[j]) < 0) && (j < strlen(str))){
						j++;
					}
					k = 0;
					while (j < strlen(str)){
						word_t[k] = str[j];
						k++;
						j++;
						if (poscinstr(letters, str[j]) <0){
							word_t[k] = '\0';
							if ((strlen(word_t) < 11) && (strlen(word_t) > 0)) {
								insert(a, word_t);
							}
							k = 0;
							while ((poscinstr(letters, str[j]) < 0) && (j < strlen(str))){
								j++;
							}
						}
					}
					word_t[k] = '\0';
					if ((strlen(word_t) < 11) && (strlen(word_t) > 0)) {
						insert(a, word_t);
					}
				}
				if (fopen_s(&f, argv[4], "w") == 0)
				{
					prntable_f(a, f);
					fclose(f);
				}
				else{
					printf("Output file not opened.");
					getchar();
					break;
				}
				break;
			}
			else{
				printf("Input file not opened.");
				getchar();
				break;
			}
		}
	}
	return;
}

...
Рейтинг: 0 / 0
03.12.2016, 19:36
    #39359906
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
В студии работает, а в консоли вылетает(Си)
vlladimirа при запуске из консоли вылетает
А она, случайно так, при этом не пишет "многа нипанятных букафф", включающих в себя точную
причину и место ошибки, а так же call stack, приведших к этому?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
03.12.2016, 20:03
    #39359913
vlladimir
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
В студии работает, а в консоли вылетает(Си)
Dimitry Sibiryakov, Нет просто вылетает и все (Прекращена работа программы)
...
Рейтинг: 0 / 0
03.12.2016, 21:00
    #39359923
egorych
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
В студии работает, а в консоли вылетает(Си)
vlladimirНет просто вылетает и всене удивительно
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
void prntable(struct node *a[255]){
	int i;
	node *p;
	for (i = 0; i < 256; i++){
		p = a[i];
		while (p){
			printf("%s %d\n", p->word, p->count);
			p = p->next;
		}
	}
}

выход за пределы массива всегда заканчиваются не приятно
...
Рейтинг: 0 / 0
03.12.2016, 21:21
    #39359928
alexy_black
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
В студии работает, а в консоли вылетает(Си)
"что только не делают люди чтобы не использовать ..." wc
или вот так "юзай wc а то будет wc" :)
...
Рейтинг: 0 / 0
03.12.2016, 22:58
    #39359944
Пётр Седов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
В студии работает, а в консоли вылетает(Си)
vlladimir
Код: plaintext
1.
2.
3.
	struct node *n, ...;
	...
		n = (node*)malloc(sizeof(node*));

Вы запрашиваете блок памяти размером с указатель, а надо запрашивать блок памяти размером с node:
Код: plaintext
1.
n = (node*)malloc(sizeof(node));


vlladimir
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
int poscinstr(char *str, char c)
{
	unsigned int i;
	for (i = 0; i < strlen(str); i++){
		if (str == c){
			return i;
		}
	}
	return -1;
}

Так лучше не писать, потому что функция strlen вызывается на [i]каждой
итерации цикла. Вообще, для поиска char-а в ноль-завершаемой строке есть стандартная функция strchr :
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
#include <string.h>

int find_char(const char s[], char c) {
  const char* p;
  p = strchr(s, c);
  return (p != NULL ? (int)(p - s) : -1);
}


vlladimir
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
	node *a[256];
	...
	unsigned int j;
	...
	for (j = 0; j < 256; j++){
		a[j] = (node*)malloc(sizeof(node*));
		a[j] = NULL;
	}

Отмеченная строка не нужна.

vlladimir
Код: plaintext
1.
estr = fgets(str, 2000, fi);

Все современные компьютеры оснащены гигабайтами оперативной памяти, поэтому при работе с текстовыми файлами в большинстве случаев нет смысла заморачиваться на чтение файла по кусочкам. Проще загрузить весь файл в один буфер, и работать с ним как с большой строкой, например так:
Код: plaintext
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.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

char* load_text_file(const char path[]) {
  FILE* file;
  size_t size;
  char* text;

  /* 'b' чтобы не тратить время на замену "\r\n" (CR LF) -> "\n" (LF) */
  file = fopen(path, "rb");

  /* узнаём размер файла */
  fseek(file, /*offset:*/0, SEEK_END);
  size = ftell(file);
  fseek(file, /*offset:*/0, SEEK_SET);

  text = (char*)malloc(size + 1);
  fread(text, 1, size, file);
  text[size] = '\0';

  fclose(file);

  return text;
}

bool is_letter(char c);
void handle_word(const char word[], size_t word_len);

void load_words(const char file_path[]) {
  char* text;
  size_t pos, word_pos;

  text = load_text_file(file_path);

  pos = 0;
  for (;;) {
    /* пропускаем не-буквы */
    for (;;) {
      if (is_letter(text[pos]) || (text[pos] == '\0'))
        break;
      pos++;
    }

    if (text[pos] == '\0')
      break;

    /* сканируем слово */
    word_pos = pos;
    pos++; /* пропускаем первую букву */
    while (is_letter(text[pos]))
      pos++;

    handle_word(text + word_pos, /*word_len:*/ pos - word_pos);
  }

  free(text);
}

bool is_letter(char c) {
  return (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z'));
}

void handle_word(const char word[], size_t word_len) {
  /* строка word не завершается нулевым char-ом ('\0'), поэтому явно указываем длину */
  printf("%.*s\n", (int)word_len, word);
}

Обработку ошибок не писал, чтобы код был проще. Но по-хорошему, ошибки надо обрабатывать. Есть два способа: коды возврата и исключения ( setjmp / longjmp , или тупо exit ). Какой способ лучше -- holy war.

egorychvlladimirНет просто вылетает и всене удивительно
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
void prntable(struct node *a[255]){
	int i;
	node *p;
	for (i = 0; i < 256; i++){
		p = a[i];
		while (p){
			printf("%s %d\n", p->word, p->count);
			p = p->next;
		}
	}
}

выход за пределы массива всегда заканчиваются не приятноА там как раз массив длины 256:
vlladimir
Код: plaintext
1.
2.
3.
void main(int argc, char *argv[]) {

	node *a[256];

поэтому с индексом всё нормально. А то, что в заголовках функций написано «struct node *a[255]», значения не имеет, потому что длина массива реально не передаётся. Но лучше конечно поправить, а то сбивает с толку.
...
Рейтинг: 0 / 0
04.12.2016, 05:13
    #39359980
vlladimir
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
В студии работает, а в консоли вылетает(Си)
Пётр Седов, Спасибо огромное!
n = (node*)malloc(sizeof(node));
Дело было в этой строке, после правки все заработало, ну и кое-что еще поправил по вашим советам, еще раз спасибо!!!
...
Рейтинг: 0 / 0
05.12.2016, 11:23
    #39360330
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
В студии работает, а в консоли вылетает(Си)
vlladimirПётр Седов, Спасибо огромное!
n = (node*)malloc(sizeof(node));
Дело было в этой строке, после правки все заработало, ну и кое-что еще поправил по вашим советам, еще раз спасибо!!!


не, дело не только в этой строке...
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / В студии работает, а в консоли вылетает(Си) / 8 сообщений из 8, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]