2013-09-15 4 views
-1

CSCI-15 Назначение # 2, Обработка строк. (60 баллов) Долг 9/23/13Подсчитайте количество уникальных слов и появление каждого слова

Вы НЕ МОЖЕТЕ использовать строковые объекты C++ для чего-либо в этой программе.

Напишите программу на C++, которая читает строки текста из файла с использованием метода ifstream getline(), тонизирует строки в словах («токены») с использованием strtok() и сохраняет статистику по данным в файле. Имена ваших входных и выходных файлов будут добавлены в вашу программу в командной строке, к которой вы будете обращаться, используя argc и argv[].

Вам нужно посчитать общее количество слов, количество уникальных слов, количество каждого отдельного слова и количество строк. Кроме того, запомните и напечатайте самые длинные и кратчайшие слова в файле. Если есть связь для самого длинного или кратчайшего слова, вы можете разрешить связь любым способом (например, использовать либо первый, либо последний найденный, но использовать тот же самый метод как для самого длинного, так и для кратчайшего). Вы можете предположить, что строки содержат слова (смежные строчные буквы [a-z]), разделенные пробелами, заканчивающиеся периодом. Вы можете игнорировать возможность других знаков препинания, включая притяжательные или схватки, например, в «доме Джима». Строки перед последним в файле будут иметь новую строку ('\ n') после периода. В ваших файлах данных опустите '\ n' в последнюю строку. Вы можете предположить, что строки будут не более 100 символов, отдельные слова будут не длиннее 15 букв, и в файле будет не более 100 уникальных слов.

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

Тестовый файл выглядит следующим образом (ровно 4 строк, с NO NEWLINE на последней строке):

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

Скопируйте и вставьте это в небольшой файл для одного из ваших тестов.

советы:

Используйте 2-мерный массив полукокса, 100 строк по 16 столбцов, чтобы держать уникальных слов, а 1-мерный массив целых чисел с 100 элементами, чтобы держать (почему не 15?) связанные счетчики. Для каждого слова просматривайте занятые строки в массиве для соответствия (используйте strcmp()), и если вы найдете совпадение, увеличьте соответствующий счетчик, в противном случае (вы прошли последнее слово), добавьте слово в таблицу и установите его количество до 1.

Разделение самого длинного слова и кратчайшего слова должно быть сохранено в их собственных C-строках. (Почему вы не можете просто держать указатель на них в токенах данных?)

Помните - поставьте NO NEWLINE в конце последней строки или ваш тест на конец файла может работать неправильно. (Это может привести к тому, что программа прочитает строку нулевой длины перед просмотром конца файла.)

Это не длинная программа - не более чем около 2 страниц кода

Вот то, что я до сих пор:

#include<iostream> 
#include<iomanip> 
#include<fstream> 
#include<string> 
#include<cstring> 
using namespace std; 

void totalwordCount(ifstream &inputFile) 
{ 
    char words[100][16]; // Holds the unique words. 
    char *token; 
    int totalCount = 0; // Counts the total number of words. 
    // Read every word in the file. 
    while(inputFile >> words[99]) 
    { 
     totalCount++; // Increment the total number of words. 
     // Tokenize each word and remove spaces, periods, and newlines. 
     token = strtok(words[99], " .\n"); 
     while(token != NULL) 
     { 
      token = strtok(NULL, " .\n"); 
     } 
    } 
    cout << "Total number of words in file: " << totalCount << endl; 
} 

void uniquewordCount(ifstream &inputFile) 
{ 
    char words[100][16]; // Holds the unique words 
    int counter[100]; 
    char *tok = "0"; 
    int uniqueCount = 0; // Counts the total number of unique words 
    while(!inputFile.eof()) 
    { 
     uniqueCount++; 
     tok = strtok(words[99], " .\n"); 
     while(tok != NULL) 
     { 
      tok = strtok(NULL, " .\n"); 
      inputFile >> words[99]; 
      if(strcmp(tok, words[99]) == 0) 
      { 
       counter[99]++; 
      } 
      else 
      { 
       words[99][15] += 1; 
      } 
      uniqueCount++; 
     } 
    } 
    cout << counter[99] << endl; 
} 

int main(int argc, char *argv[]) 
{ 
    ifstream inputFile; 
    char inFile[12] = "string1.txt"; 
    char outFile[16] = "word result.txt"; 

    // Get the name of the file from the user. 
    cout << "Enter the name of the file: "; 
    cin >> inFile; 

    // Open the input file. 
    inputFile.open(inFile); 

    // If successfully opened, process the data. 
    if(inputFile) 
    { 
     while(!inputFile.eof()) 
     {   
      totalwordCount(inputFile); 
      uniquewordCount(inputFile); 
     } 
    } 
    return 0; 
} 

я уже позаботилась о том, как подсчитать общее число слов в файле в функции totalwordCount(), но в функции uniquewordCount() у меня возникают проблемы с подсчетом общего количества уникальных слов и подсчета количества вхождений каждого слова. Есть ли что-то, что мне нужно изменить в функции uniquewordCount()?

+5

Я настоятельно рекомендую найти лучший класс C++! Нет смысла думать, как программировать C, когда целью является изучение C++! Это утверждение совершенно смешно: «Помните - поставьте NO NEWLINE в конце последней строки, или ваш тест на конец файла может работать неправильно.«Вместо того, чтобы давать вам тайные советы, ваш учитель должен скорее узнать, как правильно читать данные на C++! –

+5

Это не выглядит так хорошо. Вам далеко не понять, что вы делаете, и 95% этого кода должны быть выброшенным.Это даже не близко к правильному.Я думаю, вам действительно нужно сесть с кем-то, у которого есть время, чтобы пройти это упражнение с вами. Вы получите больше понимания от взаимодействия с реальным человеком, чем вы от этого форума. Этот форум действительно очень хорош, отвечая на конкретные вопросы, это на самом деле не подходит для правильного преподавания. – john

+0

Я второй, что говорит Дитмар, это не поможет вам получить такое дерьмовое упражнение. – john

ответ

4

Эта программа содержит несколько продуктов, которые считаются вредоносными! Для того, чтобы предотвратить плохое программное обеспечение создается на основе совершенно бессмысленные задания, как выше, вот несколько подсказок:

  1. Всегда тест потока для успеха после чтения из него. Используя in.eof(), чтобы определить, находится ли поток в хорошем состоянии, не работа! Одна из проблем заключается в том, что вы получите бесконечный цикл, если поток пойдет по другому причинам, кроме конца файла, например, при неправильном анализе значения (это установит std::ios_base::failbit, но не std::ios_base::eofbit.
  2. Чтение на фиксированный размер char массив a с использованием in >> a без установки ограничений на количество символов, которые нужно читать, это способ C++ для написания gets()! Если вы действительно думаете, что использование in >> a - это правильный путь (см. следующий пункт), вы должны абсолютно необходимо настройте ширину массива, например, используя in >> std::setw(sizeof(a)) >> a. Вам все равно нужно проверить, что это извлечение было успешным, конечно.
  3. От взглядов из этого, ваш учитель хочет, чтобы вы фактически использовали std::istream::getline() для чтения массива, например, используя in.getline(a, sizeof(a)) (что, конечно же, необходимо проверить на успех).
  4. Обратите внимание, что форматированный вход, т. Е. in >> a, уже расшифровывает поток, принимаемый пробелами! После этого не нужно начинать с strtok().
  5. Как только вы потребляете поток, он потребляется. Предполагая, что символы получены не из файла, а скорее из чего-то вроде стандартного ввода, вы также не можете перемотать поток, чтобы прочитать его снова. Я бы подумал, что вы хотите один раз идентифицировать значения и использовать их для обеих целей.
  6. Это больше связано с сайтом: после создания потока его характер должен быть совершенно несущественным для обработки содержимого потока (хотя, например, для потоковых потоков вы можете, в конечном счете, собрать результат, используя элемент str()) : реализовать функции обработки потока в терминах std::istream, а не std::ifstream!

Поскольку у вас есть конкретный вопрос («Есть ли что-нибудь, что мне нужно изменить в функции uniquewordCount()?): Да, все! Полностью отбросьте эту функцию и переосмыслите то, что вам нужно сделать. В принципе, структура функциональности должна быть в строках

char buffer[100]; 
while (in.getline(buffer, sizeof(buffer))) { 
    // tokenize buffer into words 
    // for each word check if it already exists 
    // if the word does not exist, append it to the array of known words and set count to 1 
    // if the word exists, increment the count 
    // determine if the word is shorter or longer than the shortest or longest word so far 
    // if it is the case, remember the word's index or a pointer to it 
} 
Смежные вопросы