Форум: Форум C++Разное
Новые темы: 00
PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум C++

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Сколько раз повторяется буква
 
 автор: lestat89   (04.03.2012 в 18:01)   письмо автору
 
 

Пишу курсовик.
Нужно посчитать сколько каждая буква повторяется в тексте.
Вот мой код.
#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:05)   письмо автору
 
   для: lestat89   (04.03.2012 в 18:01)
 

Блин сорри писал в C++ тема тут появилась и то с 5 раза... Надеюсь модераторы перенесут, ибо не создается больше.

  Ответить  
 
 автор: cheops   (05.03.2012 в 16:19)   письмо автору
 
   для: lestat89   (04.03.2012 в 18:01)
 

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

  Ответить  
 
 автор: KernelPanic   (05.03.2012 в 17:01)   письмо автору
 
   для: 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 это понятно.
Вопрос - что происходит в данном случае, т.е. по какому алгоритму отрабатывает код?
Как это будет правильно?
Что будет, если объявление сделать так:
  char key;
?
выдает при компиляции [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;
}

Но хотел то ввод по другому осуществить.

  Ответить  
 
 автор: cheops   (05.03.2012 в 17:44)   письмо автору
7.6 Кб
 
   для: KernelPanic   (05.03.2012 в 17:01)
 

Следует понимать, что массивы и указатели в C это одно и тоже. Используя только имя, не указывая на конкретный элемент нельзя производить сравнение с базовым типом. Вот так не правильно
int arr[50];
int num;
...
if(arr == num)
это попытка сравнить 50 целых значений с одним - нужны телодвижения, чтобы из 50 элементов выбрать один. Указатели это те же массивы, только более гибкие (хотя и более сложные в использовании). Если не сложно гляньте картинку во вложении (там массив из 4 элементов представлен в двух одинаковых формах - это совершенно две одинаковы с точки зрения C записи того, факта, что в области памяти идет 4 элемента char подряд, только в массиве это указано явно, а в указателе это знание придется передавать как-то иначе). Поэтому когда вы берете в руки указатель, нужно обязательно с ним что-то сделать (причем не вылазя за границы области памяти, на которую он указывает), так как он указывает на много элементов... вам же нужно из этой массы взять один элемент. Т.е. нельзя писать так
key == byte
можно сравнивать отдельные элементы, так
key[0] == (char)byte
или так
(int)*key == byte
иначе компилятор протестует и правильно делает.

  Ответить  
 
 автор: cheops   (05.03.2012 в 17:56)   письмо автору
 
   для: KernelPanic   (05.03.2012 в 17:01)
 

Есть и другой вариант, сравнить две строки при помощи библиотечной функции, либо написать собственные классы-строк, которые перегрузят оператор сравнения ==, или воспользоваться готовыми строками String (т.е. класс String уже написали до нас). Однако, на самом низком уровне - этого ничего нет нельзя просто взять и сравнить две строки - это системный язык, вы отвечаете тут за каждый байт (поэтому такое чудовищное количество ошибок в C++-программах, даже имея огромный опыт не сложно ошибиться, поэтому так популярен ООП: можно вылизать класс и быть уверенным, что вот он то уже не подведет - нужно искать ошибку в свежем коде).

PS Если вы знакомы с другими языками программирования вас в C++ будет ждать огромное количество сюрпризов, которые решаются библиотеками (стандартными и не очень), собственным кодом, а в других языках решения уже встроены на уровне языка, там зачастую и проблем таких нет, с которыми в C/C++ нужно ежеминутно бороться (правда проблемы решены за счет скорости и гибкости).

  Ответить  
 
 автор: cheops   (05.03.2012 в 18:02)   письмо автору
 
   для: KernelPanic   (05.03.2012 в 17:01)
 

>Что будет, если объявление сделать так:
> char key;
>выдает при компиляции [Warning] assignment makes integer from pointer without a cast
>if (key == byte)
Вы сравниваете два разных типа. Компилятор говорит, вижу вы сравниваете количество яблок с породой лошадей - это неправильно. Да в C++ строгая типизация и не хорошо сравнивать разные типы, но часто требуется, особенно тут когда целочисленный код равен коду char. Поэтому вы можете привести тип при помощи круглых скобок () так
if (key == (char)byte)
или так
if ((int)key == byte)
размеры типов равны и никаких проблем не должно возникнуть - компилятор будет знать, что все в порядке, мы разным количеством яблок обозначаем разные породы лошадей - так задумано и программист знает, что делает.

  Ответить  
 
 автор: KernelPanic   (06.03.2012 в 01:27)   письмо автору
 
   для: cheops   (05.03.2012 в 18:02)
 

Спасибо, что объяснили приведение типов. Я этого не знал.
Но в моем случае как понимаю - это не будет работать.
Про библиотечные функции тоже интересно. Я часто ими избегаю пользоваться, и подключать лишние файлы тоже - пока не понял до конца как все это хозяйство работает.
А почему не работает - так понял key у меня не может быть int и в цикл if у меня вхождений тогда не будет. А (char)byte сравнивать с key тоже некорректно будет...
Так и так не работает - попытался понять почему... и понял, что я даже в своем коде туго ориентируюсь спустя несколько часов(какое-то извращение получилось у меня на С).

  Ответить  
 
 автор: cheops   (06.03.2012 в 01:38)   письмо автору
 
   для: 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 Если наводящие/новые вопросы появятся, давайте для них новую тему заведем, чтобы потом их искать и ссылаться на них удобнее было.

  Ответить  
 
 автор: lestat89   (17.04.2012 в 10:55)   письмо автору
 
   для: cheops   (06.03.2012 в 01:38)
 

По поводу вышенаписаного вот интересно как выделить место под файл не зная сколько он может весить ?

  Ответить  
 
 автор: alsav22   (17.04.2012 в 15:12)   письмо автору
 
   для: lestat89   (17.04.2012 в 10:55)
 

Через объекты всё решается. Можно скопировать файл в объект с автоматическим управлением памятью (например, vector<char> или string). Можно никуда не копировать весь файл. Создать объект класса ifstream и отрыть с его помощью нужный файл для чтения: ifstream readFile("txtfile.txt"), и потом посимвольно считывать файл в символьную переменную ch: readFile.get(ch), с дальнейшим анализом.

  Ответить  
 
 автор: cheops   (17.04.2012 в 22:08)   письмо автору
 
   для: lestat89   (17.04.2012 в 10:55)
 

А что с файлом хотите делать? Читать его в память? Или наоборот хотите сначала файл создать нужного размера, а потом с ним работать?

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования