I have a text file that (partial snippet) looks like the following:

Bugs Bunny Jr. 1234 1001.01
Porky Pig 2345 1002.02

Its format is a name (including spaces) is 20 characters, then 4 digit number, a space, and a number thats not a set number of characters.

I have to read the name, first set of numbers (pin), and last numbers (balance) into a linked list struct. The trouble I am running into is the name portion. I made name a char array of 20 chars, but when it reads in it skips the whitespaces and reads the numbers as well as the name. Is there a way to get the input operator to count spaces as a character so it will not skip them? Also someone mentioned I could use a cstring instead of a char array but didn't elaborate, so didn't help me at all. Any help would be appreciated!
I am using DEV C++ on winxp (if that makes any difference).

Here is what I have

ifstream fin;

struct customerType{
       char name[20];
       int pin;
       float balance;
       customerType *link;
       };


int main(){
    customerType *head, *curptr, *nnptr;
    fin.open("input.txt");
    if(!fin){
         cout << "File not found\n";
         system("pause");
         return 0;
    }
    head = new customerType;

    for(int i=0; i<20; i++)
    {
    fin >> head->name[i];
    }//END FOR
    fin >> head->pin >> head->balance;
    curptr = head;
    
    while(fin)
    {
         nnptr = new customerType;
         for(int i=0; i<20; i++)
         {
         fin >> nnptr->name[i];
         } // END FOR
         fin >> nnptr->pin >> nnptr->balance;
         curptr->link = nnptr;
         curptr = nnptr;
         if(fin.peek()=='\n')fin.ignore();
    } //END WHILE
    curptr->link = NULL;
    curptr = NULL;
    nnptr = NULL;
}//END MAIN

Dani AI

Generated

The problem is that formatted extraction with operator>> treats whitespace as a delimiter, so reading characters with fin >> head->name[i] will skip spaces. Two common, safer patterns are (A) read the entire input line and parse it, or (B) use unformatted reads that do not skip whitespace. Using std::string for the name makes life much easier (no manual null-termination or overflow worries).

As suggested, a simple, robust approach is: read each line with std::getline, take the first 20 columns as the name (trim trailing spaces), then parse the remainder with std::istringstream to extract pin and balance. This handles names with internal spaces and variable spacing between fields without fiddling with skipws. Example parsing loop (illustrative, keep struct and storage separate from this snippet):

#include <string>
#include <sstream>

std::string line;
while (std::getline(fin, line)) {
    std::string name = line.size() > 20 ? line.substr(0,20) : line;
    while (!name.empty() && name.back() == ' ') name.pop_back(); // rtrim
    std::istringstream iss(line.size() > 20 ? line.substr(20) : "");
    int pin = 0; double balance = 0.0;
    iss >> pin >> balance;
    // validate iss and then store name, pin, balance into node
}

If the file really uses fixed-width fields, ’s suggestion to read exactly N bytes is valid — use fin.read(buffer, N) or the member fin.getline(buffer, N+1) but remember to allocate N+1 bytes so there’s room for the terminating \0, and trim trailing spaces. Another less-common alternative is to temporarily clear the skipping flag (fin >> std::noskipws) and read exactly 20 characters into a buffer, then restore std::skipws; that works but is fiddlier.

Final notes: prefer std::string to avoid off-by-one and overflow bugs, always check parsing success (validate iss), and be aware of CR/LF or non-printable characters if the file crosses platforms.

Recommended Answers

All 3 Replies

Another thought, is there a way to limit a string input to 20 characters? ex, replace the name char array with string name and have fin>> head->name stop at 20 characters?

You could probably write your own >> operator, but if you use the regular >> operator, it's going to use white space as a delimiter. getline may be useful. Depending which getline you use, you can it to read up to 20 characters or up to a specified delimiter.


strtok could come in useful here too.

You can use get and read a character at a time and use isalpha , isspace , and isdigit from the cctype library.

Here's an example using strtok to peel off everything in a C-Style string up to the first digit.

#include <cstring>
#include <iostream>
using namespace std;

int main ()
{
    char aString[20] = "abc def ghi  54";
    char* letters = strtok (aString, "0123456789");
    cout << letters << endl;
    cin.get (); 
    return 0;
}

>Its format is a name (including spaces) is 20 characters, then 4 digit number, a space, and a number thats not a set number of characters.
Probably it's a wrong line format description (judging by the file contents example the name field has not fixed width). However if it's true, you may use read member function to get a fixed number of chars from the stream (change the target as you wish):

char name[21];
...
fin.read(name,20);
name[20] = '\0'; // terminate a string in C style.

Take into account that now customerType::name array can contain 19-char strings only + terminating zero byte. If you want to process names as strings in C style you must reserve at least 21 char for name member array.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.