简体   繁体   English

从 txt 文件中读取字符,然后打印到数组 c++

[英]Reading characters from txt file then printing the into array c++

So I am trying to read a text file and enter them into an "char" array, and I want each row to be entered as one entry, I have this so far but it only enters one symbol at a time.所以我试图读取一个文本文件并将它们输入一个“char”数组,我希望每一行都作为一个条目输入,到目前为止我有这个但它一次只输入一个符号。

txt file: txt文件:

QA310
95
47
50
CM145
320
162
200
MS514
34
20
25
EN212
163
150
160

Code to read the file:读取文件的代码:

for (int i = 0; i < SIZE; i++)
    {
        inFile >> product1[i];
    }

    for (int i = 4; i < 7; i++)
    {
        inFile >> product2[i-4];
    }

    for (int i = 7; i < 11; i++)
    {
        inFile >> product3[i-7];
    }

    for (int i = 11; i < 15; i++)
    {
        inFile >> product4[i-11];
    }

    outFile << product1[0] << endl;
    outFile << product2[0] << endl;
    outFile << product3[0] << endl;
    outFile << product4[0] << endl;

Please clarify, but I think you want sets of 4 rows combined.请澄清,但我认为你想要组合 4 行。

[edit] Modified code to match string in the comment. [编辑] 修改代码以匹配注释中的字符串。

#include "Header.h"
#include <fstream>
#include <string>
#include <vector>
#include <iostream>

using namespace::std;

typedef struct _product {
   wstring code;
   vector<int> numbers;
} Product;

bool isproduct(const wstring& txtrow, int currentrow, int interval = 4)
{
   //// assumes non-numeric product
   //if (stoi(txtrow) > 0)
   //   return false;
   //else
   //   return true;

   // assumes constant pattern
   if ((currentrow % interval) == 1)
      return true;
   else
      return false;
}

void parsefile(wstring filepath)
{
   wfstream inFile(filepath);
   vector<Product> list;

   Product prod;
   int rowcount = 0;
   while (!inFile.eof()) {
      wstring txtrow;
      inFile >> txtrow;
      if (txtrow.empty())
         continue;

      rowcount++;
      if (isproduct(txtrow, rowcount)) {
         // add product to list
         if (!prod.code.empty())
            list.push_back(prod);

         // start next
         prod.code = txtrow;
         prod.numbers.clear();
      }
      else
         prod.numbers.push_back(std::stoi(txtrow));
   }

   // add final product to list
   if (!prod.code.empty())
      list.push_back(prod);

   for (vector<Product>::iterator idx = list.begin(); idx != list.end(); idx++) {
      std::wcout << idx->code << L"   ";
   }

   std::wcout << std::endl;
}

Make the product1, product2... , etc., arrays of strings, not chars.制作字符串的product1,product2 product1, product2...等,arrays,而不是字符。 Otherwise, each position of the char array holds just one char, which means the "0" index of each array will always be just a single char.否则,char 数组的每个 position 仅包含一个 char,这意味着每个数组的“0”索引将始终只有一个 char。

Then, read in the file by line.然后,逐行读入文件。 If it is catching more than one line for any reason, you can delimit by the new-line character \n , but here I use getline:如果由于任何原因它捕获多行,您可以用换行符\n分隔,但这里我使用 getline:

string[] product1;
string[] product2;
string[] product3;
string[] product4;

ifstream file;
file.open("products.txt");
string line;
int count = 0;

while(getline(file, line)) {
    if (count < 4) {
        product1[count];
    } else if (count < 8) {
        product2[count-4];
    } else if (count < 12) {
        product3[count-8];
    } else if (count < 16) {
        product4[count-12];
    }
    count++;
}

cout << product1[0] << endl;
cout << product2[0] << endl;
cout << product3[0] << endl;
cout << product4[0] << endl;

Finally, I suggest finding a more programmatic way than to put each product in its own hard-coded array.最后,我建议找到一种比将每个产品放在自己的硬编码数组中更编程的方式。 For instance, instead of product1, product2... , etc., you could make a struct that holds the numbers in an array of integers, and just make one of those every four lines of text (or at a delimiter).例如,您可以创建一个将数字保存在整数数组中的struct ,而不是product1, product2...等,然后每四行文本(或在分隔符处)创建一个。 Then you could just create another loop to print out/manipulate each and every one, instead of manually typing them all out.然后,您可以创建另一个循环来打印/处理每个循环,而不是手动将它们全部输入。

So the biggest thing to avoid is writing a specialized input routine that relies on taking different actions based on a counter (that is appropriate in some cases, but not here).所以要避免的最重要的事情是编写一个专门的输入例程,该例程依赖于基于计数器采取不同的操作(这在某些情况下是合适的,但在这里不适用)。 Better, if you can distinguish your product ID because the start with [AZ] , then use an isalpha() check, and if it is, just add the ID to a std::vector<std::string> to keep track of your product.更好的是,如果您可以区分您的产品 ID,因为以[AZ]开头,然后使用isalpha()检查,如果是,只需将 ID 添加到std::vector<std::string>以跟踪你的产品。 If it isn't an alph-character, then simply add it to a temporary std::vector<std::string> and build a list of products associated with the last-read ID.如果它不是字母字符,则只需将其添加到临时std::vector<std::string>并构建与上次读取 ID 关联的产品列表。 When you encounter the next product ID, just write the temporary vector to a std::vector<std::vector<std::string>> that will hold the vectors of products associated with each product ID.当您遇到下一个产品 ID 时,只需将临时向量写入std::vector<std::vector<std::string>>将保存与每个产品 ID 关联的产品向量。

You can write a very simple input loop to handle this situation, for example:您可以编写一个非常简单的输入循环来处理这种情况,例如:

    std::string line;                                   /* string for line */
    std::vector<std::string> prodid{}, tmp{};           /* prod ID & tmp vector */
    std::vector<std::vector<std::string>> products{};   /* vector vector products */
    size_t n = 0;                                       /* simple counter */

    while (getline (f, line)) {             /* read each line */
        if (isalpha(line.at(0))) {          /* if it starts with alpha char */
            prodid.push_back(line);         /* save it as prod ID */
            if (tmp.size())                 /* if tmp populated */
                products.push_back(tmp);    /* save in products */
            tmp.clear();                    /* clear temporary vector */
        }
        else    /* otherwise */
            tmp.push_back(line);            /* line is product, add to tmp */
    }
    if (tmp.size())                         /* check if tmp populated */
        products.push_back(tmp);            /* add final vector of products */

Which is a simple read-loop with a single if/else and a final check on whether the temporary vector is populated on loop exit, and if so, and the contents of the temporary vector to your vector of vector containing products.这是一个简单的读取循环,带有一个if/else ,最后检查是否在循环退出时填充了临时向量,如果是,以及临时向量的内容到包含产品的向量的向量。

The to output the storage information, you can simply use an range-based for loop to iterate over your vector of vector holding products.对于 output 的存储信息,您可以简单地使用基于范围的for循环来迭代您的向量持有产品的向量。 You output the product ID, and then use another range based for loop to iterate over each product in the current vector outputting in whatever format you like.您 output 产品 ID,然后使用另一个基于范围的for循环迭代当前向量中的每个产品,以您喜欢的任何格式输出。 The counter variable n is used to increment the product ID associated with the current vector of products, eg计数器变量n用于递增与当前产品向量关联的产品 ID,例如

    for (auto id : products) {              /* loop over products vector of vector */
        std::cout << prodid[n++] << ": ";   /* output prod ID wtih counter */
        for (auto prod : id)                /* loop over product record */
            std::cout << " " << prod;       /* outputting each product */
        std::cout << '\n';                  /* tidy up with '\n' */
    }

Putting the whole thing together, adding the headers required and taking the filename to read as the first argument to the program, and adding the necessary validations, you would have:将整个事情放在一起,添加所需的标头并将要读取的文件名作为程序的第一个参数,并添加必要的验证,您将拥有:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cctype>

int main (int argc, char **argv) {

    if (argc < 2) { /* validate 1 argument given for filename */
        std::cerr << "error: insufficient input\n"
                    "usage: " << argv[0] << " filename\n";
        return 1;
    }

    std::ifstream f (argv[1]);  /* open file, validate file open for reading */
    if (!f.is_open()) {
        std::cerr << "file open failed.\n";
        return 1;
    }

    std::string line;                                   /* string for line */
    std::vector<std::string> prodid{}, tmp{};           /* prod ID & tmp vector */
    std::vector<std::vector<std::string>> products{};   /* vector vector products */
    size_t n = 0;                                       /* simple counter */

    while (getline (f, line)) {             /* read each line */
        if (isalpha(line.at(0))) {          /* if it starts with alpha char */
            prodid.push_back(line);         /* save it as prod ID */
            if (tmp.size())                 /* if tmp populated */
                products.push_back(tmp);    /* save in products */
            tmp.clear();                    /* clear temporary vector */
        }
        else    /* otherwise */
            tmp.push_back(line);            /* line is product, add to tmp */
    }
    if (tmp.size())                         /* check if tmp populated */
        products.push_back(tmp);            /* add final vector of products */

    for (auto id : products) {              /* loop over products vector of vector */
        std::cout << prodid[n++] << ": ";   /* output prod ID wtih counter */
        for (auto prod : id)                /* loop over product record */
            std::cout << " " << prod;       /* outputting each product */
        std::cout << '\n';                  /* tidy up with '\n' */
    }
}

Input File输入文件

$ cat dat/products.txt
QA310
95
47
50
CM145
320
162
200
MS514
34
20
25
EN212
163
150
160

Example Use/Output示例使用/输出

$ ./bin/product dat/products.txt
QA310:  95 47 50
CM145:  320 162 200
MS514:  34 20 25
EN212:  163 150 160

Writing a general read that will key off differences in the input allows you to read an unknown number of product IDs and an unknown number of products per-ID, so long as the difference in ID and product strings remains constant (ie the ID always begins with [AZ] and the product itself always begins [0-9] ).只要 ID 和产品字符串的差异保持不变(即 ID 始终以与[AZ]并且产品本身总是以[0-9]开头)。 This isn't the only way to do it, but a basic way of reading and storing the differing input so you can make use of the input later in your code however you like.这不是唯一的方法,而是读取和存储不同输入的基本方法,因此您可以稍后在代码中随意使用输入。

If you wanted to always maintain an alphabetically sorted list of product ID and the associated products, you could use a container that allows you to associate the prod ID with the products such as std::map <std::string, std::vector<std::string>> and avoid the need to maintain a separate list of ID's and products.如果您想始终维护按字母顺序排列的产品 ID 和相关产品列表,您可以使用允许您将产品 ID 与产品相关联的容器,例如std::map <std::string, std::vector<std::string>>并避免维护单独的 ID 和产品列表。 You can make that change with minimal effort, eg你可以用最小的努力做出改变,例如

...
#include <map>
...
    std::string line, idstr;                    /* string for line, id */
    std::vector<std::string> tmp{};             /* tmp vector */
    std::map <std::string, std::vector<std::string>> products{}; /* map id/products */

    while (getline (f, line)) {                 /* read each line */
        if (isalpha(line.at(0))) {              /* starts with alpha char? */
            if (tmp.size())                     /* if tmp populated */
                products.insert({idstr, tmp});  /* save in products */
            tmp.clear();                        /* clear temporary vector */
            idstr = line;
        }
        else    /* otherwise */
            tmp.push_back(line);            /* line is product, add to tmp */
    }
    if (tmp.size())                         /* check if tmp populated */
        products.insert({idstr, tmp});      /* add final map of id/products */

    for (auto id : products) {              /* loop over all elements of map */
        std::cout << id.first << ": ";      /* output the prod ID */
        for (auto prod : id.second)         /* loop over each product */
            std::cout << " " << prod;       /* outputting each product */
        std::cout << '\n';                  /* tidy up with '\n' */
    }

Example Use/Output示例使用/输出

$ ./bin/product_map dat/products.txt
CM145:  320 162 200
EN212:  163 150 160
MS514:  34 20 25
QA310:  95 47 50

You can use std::stoi to convert each product from a std::string to size_t .您可以使用std::stoi将每个产品从std::string转换为size_t There is no limit to what you can do.您可以做的事情没有限制。 Look things over and let me know if you have further questions.如果您还有其他问题,请仔细查看并告诉我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM