|
|
|
| Пишу курсовик.
Нужно посчитать сколько каждая буква повторяется в тексте.
Вот мой код.
#include <iostream>
#include <stdio.h>
using namespace std;
int ascii_cod(char x)
{
int a;
a = x;
return a;
}
int main ()
{
setlocale (LC_ALL, "Russian");
char* filename; // адрес файла
FILE* file; // открытый файл
char file_str[1000]; // Максимальный размер файла 1000 байт
cout << "Enter file path: \n";
cin >> filename;
file = fopen(filename,"r");
if(file)
{
fgets (file_str,1024,file);
fclose (file);
cout << "Read file:\n- - - - - - - - - - - -\n";
cout << file_str ;
}
else
cout << "Error: can not open file" << filename;
cout << "\n- - - - - - - - - - - -\n End.\n";
int allSym = sizeof(file_str);
int key = 0;
int sym[256];
// обнуление массива
for(int i = 0; i <= sizeof(sym); i++)
sym[i] = 0;
for(int i = 0; i <= allSym; i++)
{
key = ascii_cod(file_str[i]);
sym[key]++;
}
// Вывод результата
cout << "Array: \n- - - - - -\n";
for(int i = 0; i <= sizeof(sym); i++)
cout << "#" <<i<< ": " << sym[i] << "\n";
system ("PAUSE");
}
|
Не работает... :(
Windoxs xp , компилирую Dev c++ | |
|
|
|
|
|
|
|
для: lestat89
(04.03.2012 в 18:01)
| | Блин сорри писал в C++ тема тут появилась и то с 5 раза... Надеюсь модераторы перенесут, ибо не создается больше. | |
|
|
|
|
|
|
|
для: lestat89
(04.03.2012 в 18:01)
| | У вас под filename не выделена память, только указатель, который показывате черт знает куда, вы туда пишите и затираете какой-то бинарный код в программе. Под все указатели перед их использованием обязательно должна быть выделена память или используйте строки с прямым указанием их размера. | |
|
|
|
|
|
|
|
для: cheops
(05.03.2012 в 16:19)
| | Извините, что в тему залез - просто интересно стало тут...
Попробовал набросать быстренько рабочую программу подсчета символов, без каких либо проверок и другой мути... Но не тут то было.
Вначале попробовал так:
#include <stdio.h>
int main (int argc, char *argv[])
{
FILE *in;
char *key;
int byte;
if (argc !=3) {
printf ("Usage: <input_file>\n");
return 1;
}
key=argv[1];
if ((in = fopen(argv[2], "rb")) != NULL) {
int x=0;
while ((byte = getc(in)) != EOF)
{
if (key == byte)
x++;
}
fclose(in);
printf ("%d", x);
}
return 0;
} |
Понимаю - ошибка в том, что нельзя сравнивать указатель и целое.
При компиляции даже ошибку выдает 24 C:\3.c [Warning] comparison between pointer and integer это понятно.
Вопрос - что происходит в данном случае, т.е. по какому алгоритму отрабатывает код?
Как это будет правильно?
Что будет, если объявление сделать так: ?
выдает при компиляции [Warning] assignment makes integer from pointer without a cast
Что в этом случае не так?
Заработала такая конструкция:
#include <stdio.h>
int main (int argc, char *argv[])
{
FILE *in;
char key;
int byte;
if (argc !=2) {
printf ("Usage: <input_file>\n");
return 1;
}
printf ("vvedite iscomii simvol\n");
scanf ("%c", &key);
if ((in = fopen(argv[1], "rb")) != NULL) {
int x=0;
while ((byte = getc(in)) != EOF)
{
if (key == byte)
x++;
}
fclose(in);
printf ("%d", x);
}
return 0;
}
|
Но хотел то ввод по другому осуществить. | |
|
|
|
|
7.6 Кб |
|
|
для: KernelPanic
(05.03.2012 в 17:01)
| | Следует понимать, что массивы и указатели в C это одно и тоже. Используя только имя, не указывая на конкретный элемент нельзя производить сравнение с базовым типом. Вот так не правильно
int arr[50];
int num;
...
if(arr == num) | это попытка сравнить 50 целых значений с одним - нужны телодвижения, чтобы из 50 элементов выбрать один. Указатели это те же массивы, только более гибкие (хотя и более сложные в использовании). Если не сложно гляньте картинку во вложении (там массив из 4 элементов представлен в двух одинаковых формах - это совершенно две одинаковы с точки зрения C записи того, факта, что в области памяти идет 4 элемента char подряд, только в массиве это указано явно, а в указателе это знание придется передавать как-то иначе). Поэтому когда вы берете в руки указатель, нужно обязательно с ним что-то сделать (причем не вылазя за границы области памяти, на которую он указывает), так как он указывает на много элементов... вам же нужно из этой массы взять один элемент. Т.е. нельзя писать так
можно сравнивать отдельные элементы, так
или так иначе компилятор протестует и правильно делает. | |
|
|
|
|
|
|
|
для: KernelPanic
(05.03.2012 в 17:01)
| | Есть и другой вариант, сравнить две строки при помощи библиотечной функции, либо написать собственные классы-строк, которые перегрузят оператор сравнения ==, или воспользоваться готовыми строками String (т.е. класс String уже написали до нас). Однако, на самом низком уровне - этого ничего нет нельзя просто взять и сравнить две строки - это системный язык, вы отвечаете тут за каждый байт (поэтому такое чудовищное количество ошибок в C++-программах, даже имея огромный опыт не сложно ошибиться, поэтому так популярен ООП: можно вылизать класс и быть уверенным, что вот он то уже не подведет - нужно искать ошибку в свежем коде).
PS Если вы знакомы с другими языками программирования вас в C++ будет ждать огромное количество сюрпризов, которые решаются библиотеками (стандартными и не очень), собственным кодом, а в других языках решения уже встроены на уровне языка, там зачастую и проблем таких нет, с которыми в C/C++ нужно ежеминутно бороться (правда проблемы решены за счет скорости и гибкости). | |
|
|
|
|
|
|
|
для: KernelPanic
(05.03.2012 в 17:01)
| | >Что будет, если объявление сделать так:
> char key;
>выдает при компиляции [Warning] assignment makes integer from pointer without a cast
>if (key == byte)
Вы сравниваете два разных типа. Компилятор говорит, вижу вы сравниваете количество яблок с породой лошадей - это неправильно. Да в C++ строгая типизация и не хорошо сравнивать разные типы, но часто требуется, особенно тут когда целочисленный код равен коду char. Поэтому вы можете привести тип при помощи круглых скобок () так
или такразмеры типов равны и никаких проблем не должно возникнуть - компилятор будет знать, что все в порядке, мы разным количеством яблок обозначаем разные породы лошадей - так задумано и программист знает, что делает. | |
|
|
|
|
|
|
|
для: cheops
(05.03.2012 в 18:02)
| | Спасибо, что объяснили приведение типов. Я этого не знал.
Но в моем случае как понимаю - это не будет работать.
Про библиотечные функции тоже интересно. Я часто ими избегаю пользоваться, и подключать лишние файлы тоже - пока не понял до конца как все это хозяйство работает.
А почему не работает - так понял key у меня не может быть int и в цикл if у меня вхождений тогда не будет. А (char)byte сравнивать с key тоже некорректно будет...
Так и так не работает - попытался понять почему... и понял, что я даже в своем коде туго ориентируюсь спустя несколько часов(какое-то извращение получилось у меня на С). | |
|
|
|
|
|
|
|
для: KernelPanic
(06.03.2012 в 01:27)
| | Вообще, конечно, нужно просто обе переменные объявить как char и не мучиться (вам же int только для x нужен)
...
char key;
char byte;
... |
>Но в моем случае как понимаю - это не будет работать.
Работать, кстати, будет, я взял вашу программу, поправил только эту строку (int)key == byte, передал файл в качестве параметра и все отлично работает (я даже вручную перепроверил - все корректно). Просто в int 3 байта из 4-х не будут работать, а будет использовать только один, однако, поверьте используя char много не съэкономите :))), процессор все-равно не умеет меньше чем 32-битами управлять, а новые так вообще 64 хотят, а это значит что каждый одно-байтный char выравнивается таким образом, чтобы его можно было "скормить" процессору в виде 4 байт. Однако компилятор считает своим долгом вас подтолкнуть к использованию двух char, что собственно всех правильнее в этом случае, поэтому и капризничает...
PS Если наводящие/новые вопросы появятся, давайте для них новую тему заведем, чтобы потом их искать и ссылаться на них удобнее было. | |
|
|
|
|
|
|
|
для: cheops
(06.03.2012 в 01:38)
| | По поводу вышенаписаного вот интересно как выделить место под файл не зная сколько он может весить ? | |
|
|
|
|
|
|
|
для: lestat89
(17.04.2012 в 10:55)
| | Через объекты всё решается. Можно скопировать файл в объект с автоматическим управлением памятью (например, vector<char> или string). Можно никуда не копировать весь файл. Создать объект класса ifstream и отрыть с его помощью нужный файл для чтения: ifstream readFile("txtfile.txt"), и потом посимвольно считывать файл в символьную переменную ch: readFile.get(ch), с дальнейшим анализом. | |
|
|
|
|
|
|
|
для: lestat89
(17.04.2012 в 10:55)
| | А что с файлом хотите делать? Читать его в память? Или наоборот хотите сначала файл создать нужного размера, а потом с ним работать? | |
|
|
|