How can I find a specific position of a character from a line of code I'm evaluating - c++

What I'm trying to do in input file stream a text document, then evaluate each character by displaying information to the user and for the use of the rest of my code. The only question I have is, if I do a loop like
myIn >> ch;
while (myIn)
{
//proceeds with code
}
That reads from file input stream, how can I find the line number and position of that character I just read in?
For example on a text document like this
Hello
How are you
I want to read in H, and say that H was found in line one, position 0. Continuing, read in w, found in position 1 line 2. Without grabbing an entire string line of code?

The only way to get the line number and character position is to count them yourself:
char c;
unsigned int character_count = 0U;
unsigned int line_number = 0U;
while (in.get(c))
{
++character_count;
if (c == '\n')
{
++line_number;
// Optional:
// character_count = 0U;
}
}
Note: the expression in>>c will skip white spaces.

Add counters for the character and line, which yoyu increase manually in the while loop.

Related

C++: How to read multiple lines from file until a certain character, store them in array and move on to the next part of the file

I'm doing a hangman project for school, and one of the requirements is it needs to read the pictures of the hanging man from a text file. I have set up a text file with the '-' char which means the end of one picture and start of the next one.
I have this for loop set up to read the file until the delimiting character and store it in an array, but when testing I am getting incomplete pictures, cut off in certain places.
This is the code:
string s;
ifstream scenarijos("scenariji.txt");
for(int i = 0; i < 10; i++ ) {
getline(scenarijos, s, '-');
scenariji[i] = s;
}
For the record, scenariji is an array with type of string
And here is an example of the text file:
example
From your example input, it looks like '-' can be part of the input image (look at the "arms" of the hanged man). Unless you use some other, unique character to delimit the images, you won't be able to separate them.
If you know the dimensions of the images, you could read them without searching for the delimiter by reading a certain amount of bytes from the input file. Alternatively, you could define some more complex rules for image termination, e.g. when the '-' character is the only character in the line. For example:
ifstream scenarijos("scenariji.txt");
string scenariji[10];
for (int i = 0; i < 10; ++i) {
string& scenarij = scenariji[i];
while (scenarijos.good()) {
string s;
getline(scenarijos, s); // read line
if (!scenarijos.good() || s == "-")
break;
scenarij += s;
scenarij.push_back('\n'); // the trailing newline was removed by getline
}
}

c++ parsing comments using string buffer

I am trying to write a code that will read in c++ files, recognize comments, and store each words in comment into a vector. My problem is that I cannot find a way to read in a single line comment.
My logic is this: If the first character in a string buffer is '/' check for second char to determine whether it is a single line or multi-line comments. If the comment is single line, read in every word delimited by whitespace until I hit new line character '\n'. If the comment is multi-line, I will read in every word until I hit another */. so the code snippet for this is,
while(!input.eof())
{
string buffer;
input >> buffer;
//check if the line is comment
if(buffer[0] == '/')
{
//single line comment
if(buffer[1] == '/')
{
//read in until I hit newlineChar, and store all words into vector
while(buffer[0] != '\n')
{
input >> buffer;
vector.add(buffer);
}
}
//multiline comment
else if(buffer[1] == '*')
{
//read until I hit */ and store all words into vector
while(buffer[buffer.size()-1] != '*' && buffer[buffer.size()] != '/')
{
input >> buffer;
vector.add(buffer);
}
}
}
}
The Problem is with my understanding of new line character. I don't quite understand how string processes the new line char. I'm assuming the string treats new line char as another delimiter just like whitespace. But even in such case, there has to be a way to recognize end of a line using string. What could be a solution to this? Any input is appreciated.
EDIT: Taking advice of user4581301, I added the while loop that reads till the end of file. And to note the problem of lines having extraction operator followed by // like
std::cout<<"//this is not a comment.";
And one way I can think of to avoid this is to read in entire line using getline and char*.
char buffer[200];
input.getline(buffer,200);
string tempStr = buffer;
vector.add(tempStr);
In this case, how can I break individual string stored in vector into words?

Logic for reading rows and columns from a text file (textparser) C++

I'm really stuck with this problem I'm having for reading rows and columns from a text file. We're using text files that our prof gave us. I have the functionality running so when the user in puts "numrows (file)" the number of rows in that file prints out.
However, every time I enter the text files, it's giving me 19 for both. The first text file only has 4 rows and the other one has 7. I know my logic is wrong, but I have no idea how to fix it.
Here's what I have for the numrows function:
int numrows(string line) {
ifstream ifs;
int i;
int row = 0;
int array [10] = {0};
while (ifs.good()) {
while (getline(ifs, line)) {
istringstream stream(line);
row = 0;
while(stream >>i) {
array[row] = i;
row++;
}
}
}
}
and here's the numcols:
int numcols(string line) {
int col = 0;
int i;
int arrayA[10] = {0};
ifstream ifs;
while (ifs.good()) {
istringstream streamA(line);
col = 0;
while (streamA >>i){
arrayA[col] = i;
col++;
}
}
}
edit: #chris yes, I wasn't sure what value to return as well. Here's my main:
int main() {
string fname, line;
ifstream ifs;
cout << "---- Enter a file name : ";
while (getline(cin, fname)) { // Ctrl-Z/D to quit!
// tries to open the file whose name is in string fname
ifs.open(fname.c_str());
if(fname.substr(0,8)=="numrows ") {
line.clear();
for (int i = 8; i<fname.length(); i++) {
line = line+fname[i];
}
cout << numrows (line) << endl;
ifs.close();
}
}
return 0;
}
This problem can be more easily solved by opening the text file as an ifstream, and then using std::get to process your input.
You can try for comparison against '\n' as the end of line character, and implement a pair of counters, one for columns on a line, the other for lines.
If you have variable length columns, you might want to store the values of (numColumns in a line) in a std::vector<int>, using myVector.push_back(numColumns) or similar.
Both links are to the cplusplus.com/reference section, which can provide a large amount of information about C++ and the STL.
Edited-in overview of possible workflow
You want one program, which will take a filename, and an 'operation', in this case "numrows" or "numcols". As such, your first steps are to find out the filename, and operation.
Your current implementation of this (in your question, after editing) won't work. Using cin should however be fine. Place this earlier in your main(), before opening a file.
Use substr like you have, or alternatively, search for a space character. Assume that the input after this is your filename, and the input in the first section is your operation. Store these values.
After this, try to open your file. If the file opens successfully, continue. If it won't open, then complain to the user for a bad input, and go back to the beginning, and ask again.
Once you have your file successfully open, check which type of calculation you want to run. Counting a number of rows is fairly easy - you can go through the file one character at a time, and count the number that are equal to '\n', the line-end character. Some files might use carriage-returns, line-feeds, etc - these have different characters, but are both a) unlikely to be what you have and b) easily looked up!
A number of columns is more complicated, because your rows might not all have the same number of columns. If your input is 1 25 21 abs 3k, do you want the value to be 5? If so, you can count the number of space characters on the line and add one. If instead, you want a value of 14 (each character and each space), then just count the characters based on the number of times you call get() before reaching a '\n' character. The use of a vector as explained below to store these values might be of interest.
Having calculated these two values (or value and set of values), you can output based on the value of your 'operation' variable. For example,
if (storedOperationName == "numcols") {
cout<< "The number of values in each column is " << numColsVal << endl;
}
If you have a vector of column values, you could output all of them, using
for (int pos = 0; pos < numColsVal.size(); pos++) {
cout<< numColsVal[pos] << " ";
}
Following all of this, you can return a value from your main() of 0, or you can just end the program (C++ now considers no return value from main to a be a return of 0), or you can ask for another filename, and repeat until some other method is used to end the program.
Further details
std::get() with no arguments will return the next character of an ifstream, using the example code format
std::ifstream myFileStream;
myFileStream.open("myFileName.txt");
nextCharacter = myFileStream.get(); // You should, before this, implement a loop.
// A possible loop condition might include something like `while myFileStream.good()`
// See the linked page on std::get()
if (nextCharacter == '\n')
{ // You have a line break here }
You could use this type of structure, along with a pair of counters as described earlier, to count the number of characters on a line, and the number of lines before the EOF (end of file).
If you want to store the number of characters on a line, for each line, you could use
std::vector<int> charPerLine;
int numberOfCharactersOnThisLine = 0;
while (...)
{
numberOfCharactersOnThisLine = 0
// Other parts of the loop here, including a numberOfCharactersOnThisLine++; statement
if (endOfLineCondition)
{
charPerLine.push_back(numberOfCharactersOnThisLine); // This stores the value in the vector
}
}
You should #include <vector> and either specific std:: before, or use a using namespace std; statement near the top. People will advise against using namespaces like this, but it can be convenient (which is also a good reason to avoid it, sort of!)

Checking for incoming data type from file

I'm reading in from a .txt file that looks something along the lines of:
int string string string
int string string
int string string string string string
where the number of string types after each int is unknown. Each line represents a new group of values and each group needs to be into their own array value or whatever (don't know if I've worded that correctly but I hope you'll understand what I mean).
Is there a check I can perform so see if the incoming data from the file is an int so that if this is true and can tell my program its a new group of data?
I've tried
int check
if(check = file1.peek()){//start new group assignment}
but this doesn't appear to work. I need to be able to use the int value once I have found that it is the next data type being read in.
Thanks in advance.
There are several ways to do this, however I would suggest that maybe your groups are on separate lines, and the spaces within a line delimit items within a group correct?
So I would read the file, line-at-a-time and then split each line on spaces.
Let me know if the above fits and then we can explain how to do it.
Ok so you can use getline:
while (cin.good()) // reading from standard input until EOF
{
String line_str;
getline(cin, line_str); // get next line from standard input
istringstream line(line_str); // put line into string stream
if (line.good()) // read from string stream until EOF
{
int x;
line >> x; // read an integer from string stream
while (line.good()) // read from string stream until EOF
{
string s;
line >> s; // read strings from string stream
/// process s
}
}
}

Read blank line C++

I am in a situation where i had a loop and everytime it reads a string but I dont know how to read blank input i.e if user enter nothing and hit enter, it remains there.
I want to read that as string and move to next input
below is the code
int times = 4;
while(times--)
{
string str;
cin>>str;
---then some other code to play with the string---
}
You would need to read the entire line using getline(). Then you would need to tokenize the strings read.
Here is a reference on using getline and tokenizing using stringstream.
char blankline[100];
int times = 4;
while(times--)
{
//read a blank line
cin.getline(blankline,100);
---then some other code to play with the string---
}