What's this code doing, and how can I manipulate it? - c++

OK. It's been a long time since I've worked with C++, and I think I've got a general idea of what this code is doing. (I am taking the relevant bits of the code, assume proper libraries are pulled in, and what not.)
ifstream inFile;
inFile.open("text.txt");
int value;
while (inFile >> value)
{
while (value > 0)
{
cout << value;
}
}
inFile.close();
So, the first while function is basically searching the input file for ints, and the second one...prints it out? Or is it that if a file's input stream can't be put to an int, it leaves the value at 0? This really compact, uncommented code is...interesting.
Anyway. If I have how the above code works, I can probably figure this out on my own, but I'm here, so may as well. If I wanted to have it only print the first (variable) number of integers in a file, what would I need to do?

If I wanted to have it only print the first (variable) number of
integers in a file, what would I need to do?
#include <fstream>
#include <iostream>
int main()
{
std::ifstream inFile{ "text.txt" };
int value;
int num_values;
std::cin >> num_values;
for(int i{}; i < num_values && (inFile >> value); ++i)
cout << value;
}

Related

C++ Can't Print Values from Array of Strings

I am having trouble with an assignment for my freshman Computer Science class.
I am trying to have PrintAllConcepts print each item of an array, once per line.
For some reason all I get is the last line printed from LIST.txt and a bunch of extra empty lines that usually end up nearly crashing the program. There appears to be no syntactical errors, so I'm afraid I am not reading the concepts into the array correctly. This is where I would like assistance.
Below is my code.
I also apologize if this seems like a noob question, as I am a beginner in C++.
Edit: Also, explaining why the Number parameter is so funky, my assignment seems to be requiring me to do it that way. That is also why PrintAllConcepts and ReadConcepts returns void.
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <iomanip>
void ReadConcepts(std::string Concepts[100], int &Number) {
std::ifstream fin;
fin.open("LIST.txt");
if (!fin.is_open()) {
std::cerr << "error: file open failed.\n";
}
std::string theConcepts[100];
std::string line;
int i;
for (i = 0; i <= 99; i++) {
while (std::getline(fin, line)) {
theConcepts[i] = line;
Number++;
}
}
}
void PrintAllConcepts(std::string Concepts[100], int Number) {
int i;
std::string line;
for (i = 0; i < Number - 1; i++) {
line = Concepts[i];
std::cout << line << std::endl;
}
std::cout << i;
}
int main() {
// Initiate variables
std::string Concepts[100];
int Number = 100;
// Read concepts
ReadConcepts(Concepts, Number);
// Open file for void function PrintAllConcepts
std::ifstream fin;
fin.open("LIST.txt");
if (!fin.is_open()) {
std::cerr << "error: file open failed.\n";
}
int i;
std::string line;
for (i = 0; i < 99; i++) {
while (std::getline(fin, line)) {
Concepts[i] = line;
}
}
PrintAllConcepts(Concepts, Number);
}
As you commented, the errors are in the ReadConcepts function.
To begin with you should not increment Number in the loop, as it's already the number of elements in the array. Because you increment Number you will pass the value 200 to PrintAllConcepts which will make it go out of bounds of the array.
Secondly you put all strings into the local array theConcepts instead of the array Concepts passed to the function. This means none of the strings in Concepts will be set, giving you the "empty" output. Remove the theConcepts array and use Concepts instead.
Thirdly you should have either the for loop, or the while loop, but not both. Since you have both the first iteration of the for loop will read all lines from the file, putting all of it into theConcepts[0], and leave the rest of the array with empty strings. I recommend a combination of both loops, as in:
for (int i = 0; i < Number && std::getline(fin, line); ++i)
{
Concepts[i] = line;
}
There are also some other "problem" that aren't serious and won't cause any errors. One of them is passing the Number argument by reference. Since Number should not be modified you should pass it by value.
As a perfunctory node to your question, you may want to insert a condition for reading the file in its entirety, i.e., while (fin.good()), etc.
That said, the above hints and tips are second to none. Debugging programs can teach you a lot, and are as good a learning tool as writing the code yourself. I should know; I'm new at this too. Good luck.
p.s.: Don't forget the good practice of closing your file once finished with it.

Printing integers from a file using an array

I'm just beginning to learn C++ and I am having some trouble with a program. It's supposed to sort numbers from an external file. I've managed to successfully code the sorting algorithm, but I am having trouble working with the external file. I am just testing some things out in a separate program to gain an understanding of how things like ifstream work. I should be able to figure out how to implement it into my program once I gain a better understanding of how it works.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
int main() {
using namespace std;
int count;
ifstream InFile;
InFile.open ("unsorted.txt");
InFile >> count;
int numbers[count];
for(int a = 0; a < count; a++)
InFile >> numbers[a];
cout << numbers << endl;
}
Currently, the output for this is 0x7ffc246c98e0 I am not sure why this is the case I'm just attempting to print my file of integers. Could anyone help explain what I am doing wrong? I'd be very thankful.
When you do
cout << numbers << endl;
you print the pointer to the first element of the array.
You want
cout << numbers[a] << '\n';
to print the current element.
Furthermore, if that's all your program is doing, then you don't actually need the array. All you need is a single int variable:
int value;
for (int a = 0; a < count; ++a)
{
InFile >> value;
cout << value << '\n';
}
That also solve the problem with the variable-length array (since there isn't any).
If you intend to use count variable to count the file size or something, it is where your code goes wrong. You can't count the length of the file as like as you are trying.
while( getline ( InFile, line ) )
{
count += line.length();
}
Maybe, try like this!!!
If you use
InFile>>count;
it would try to store all the string from InFile stream to count, which is not intended.

C++ file reading

I have a file that has a number in which is the number of names that follow. For example:
4
bob
jim
bar
ted
im trying to write a program to read these names.
void process_file(ifstream& in, ofstream& out)
{
string i,o;
int tmp1,sp;
char tmp2;
prompt_user(i,o);
in.open (i.c_str());
if (in.fail())
{
cout << "Error opening " << i << endl;
exit(1);
}
out.open(o.c_str());
in >> tmp1;
sp=tmp1;
do
{
in.get(tmp2);
} while (tmp2 != '\n');
in.close();
out.close();
cout<< sp;
}
So far I am able to read the first line and assign int to sp
I need sp to be a counter for how many names. How do I get this to read the names.
The only problem I have left is how to get the names while ignoring the first number.
Until then i cannot implement my loop.
while (in >> tmp1)
sp=tmp1;
This successfuly reads the first int from the and then tries to continue. Since the second line is not an int, extraction fails, so it stops looping. So far so good.
However, the stream is now in fail state, and all subsequent extractions will fail unless you clear the error flags.
Say in.clear() right after the first while loop.
I don't really see why you wrote a loop to extract a single integer, though. You could just write
if (!(in >> sp)) { /* error, no int */ }
To read the names, read in strings. A loop is fine this time:
std::vector<std::string> names;
std::string temp;
while (in >> temp) names.push_back(temp);
You'd might want to add a counter somewhere to make sure that the number of names matches the number you've read from the file.
int lines;
string line;
inputfile.open("names.txt");
lines << inputfile;
for(i=0; i< lines; ++i){
if (std::getline(inputfile, line) != 0){
cout << line << std::endl;
}
}
First of all, assuming that the first loop:
while (in >> tmp1)
sp=tmp1;
Is meant to read the number in the beginning, this code should do:
in >> tmp1;
According to manual operator>>:
The istream object (*this).
The extracted value or sequence is not returned, but directly stored
in the variable passed as argument.
So don't use it in condition, rather use:
in >> tmp1;
if( tmp1 < 1){
exit(5);
}
Second, NEVER rely on assumption that the file is correctly formatted:
do {
in.get(tmp2);
cout << tmp2 << endl;
} while ( (tmp2 != '\n') && !in.eof());
Although whole algorithm seems a bit clumsy to me, this should prevent infinite loop.
Here's a simple example of how to read a specified number of words from a text file in the way you want.
#include <string>
#include <iostream>
#include <fstream>
void process_file() {
// Get file name.
std::string fileName;
std::cin >> fileName;
// Open file for read access.
std::ifstream input(fileName);
// Check if file exists.
if (!input) {
return EXIT_FAILURE;
}
// Get number of names.
int count = 0;
input >> count;
// Get names and print to cout.
std::string token;
for (int i = 0; i < count; ++i) {
input >> token;
std::cout << token;
}
}

input in c++ - cin.getline

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
int T;
char J[100], S[100];
int count=0;
cin >> T;
while(T--)
{
cin.getline(J,100);
cin.getline(S,100);
puts(J);
puts(S);
for(int i=0; J[i]!='\0'; i++)
{
for(int j=0; S[j]!='\0'; j++)
{
count++;
for(int k=j; S[k]!='\0'; k++)
S[k]=S[k+1];
break;
}
}
cout << count;
}
return 0;
}
I am taking input string in J,S but during execution of program it skips the second input from the console cin.getline
I takes the test cases then takes the Strings J and S
it takes J successfully but fails to get S string ?
you need to be using a string , std::string, and calling getline as in
std::string s,j;
std::getline(std::cin,j);
std::getline(std::cin,s);
and then if you want to iterate over the contents of the strings by individual characters
for(auto i = std::begin(s); i != std::end(s); ++i)
{
std::cout << *i << std::endl;
}
use the iterators, and deference them to get the actual character values. Stay way from c strings as much as possible.
This code:
int T;
// ...
cin>>T;
...reads an int from standard input. To get it to read that int, you need to press the enter key, but this code does not remove that enter from the input buffer. Then...
cin.getline(J,100);
This tries to read a string from the input buffer, up to the first new-line character. It removes that new-line from the input buffer, but does not include it as part of the string. As such, if you don't look really closely, it appears to do essentially nothing -- i.e., you end up with an empty string.
You generally want to stick to either field-oriented input (like your cin >> T; or else line-oriented input (getline). Mixing the two, however, can be a bit tricky, especially if the getline comes after the field-oriented input. Don't get me wrong: it can work -- and work perfectly well at that, but you need to know what you're doing, and even then it can still surprise you now and again.
As noted in my comment (and #johnathon's answer) you also generally want to use std::getline to read an std::string, instead of std::cin.getline with an array of char. The latter is clumsy to deal with, even at best.
My own preference is (as a rule) to use line-oriented input throughout if you're going to use it anywhere.
std::string temp;
std::getline(std::cin, temp);
int T = lexical_cast<int>(temp);
while (T--) {
std::string j;
std::getline(std::cin, j);
// ...
As an aside, I'd also avoid using T as a name of an ordinary variable in C++. It's quite commonly used as the name of a template parameter; using it for "normal" variables is more likely to lead to confusion, especially for more advanced programmers who use templates more often.
(1)Use getchar() between cin>>T and while (T--)
as
int T;
char J[100] , S[100];
int count=0;
cin>>T;
getchar();
while(T--){
cin.getline(J,100);
cin.getline(S,100);
(2).
You can also resolve your problem in following way::
char T[10];
char J[100] , S[100];
int count=0;
getline(T,10);
while((atoi(T))--){
cin.getline(J,100);
cin.getline(S,100);
use Any 1 of them ,it will fix your problem.

Access violation reading location with simple program

Ok so I'm doing a program for class when I run across a bug I've never seen before and no idea what to do about it with only minimal experience with using the debugger, so I've come here hoping someone here can set me down the path to fixing this bug. My bug is the access violation reading location. Here is the portion of code that seems to be giving me the error:
#include "Book.h"
using namespace std;
void add (char*, char*, int);
void remove (int&);
void list ();
int Count;
Book Bookshelf [4];
int main ()
{
char* In = "";
char* N = "";
char* A = "";
int Y;
int Num;
do
{
cout << "Bookshelf> ";
cin >> In;
if (In == "add")
{
cout << "Bookshelf> Enter book: ";
cin >> N >> A >> Y;
add (N,A,Y);
}
else if (In == "remove")
{
cout << "Bookshelf> Select number: ";
cin >> Num;
remove (Num);
}
else if (In == "list")
{
}
} while (cin != "quit");
return 0;
}
void add (char* N, char* A, int Y)
{
if (Bookshelf[4].IsEmpty() == false)
cout << "Error!" << endl;
else
{
Bookshelf[Count] = Book (N,A,Y);
Count++;
}
cout << "Bookshelf> ";
}
I get the error when I type add into the command line to try to call the add function but it happens immediately so the debugger is no help to me. I know the problem is probably really simple but I can't seem to find it. Any help you can offer would be greatly appreciated. Let me know if any more code samples are needed.
You shouldn't use char* unless you really know what you are doing. For example, I rarely use char* at all and I'm programming with C++ since about 20 years. You want to use std::string, e.g. like this:
std::string In;
if (std::cin >> In) { ... }
The reason your code doesn't work is that the input operator wants to store data at the location pointed to by your pointer. However, this pointer is pointing at immutable memory for a c-string literal. When the operator tries to store something at this location it immediately gets an access violation.
The easiest fix is to use std::string. If you can't use std::string for whatever reason, use a preallocated array of char. If you do this, make sure you tell the stream how much characters are available by setting up the width:
char In[16];
if (std::cin >> std::setw(sizeof(In)) >> In) { ... }
(the reason I'm always using a check in these example is that it is very important that you always check whether your input was successful before you do anything with the result).
You cannot write data into space allocated for C-string literals: they are constants.
This is the part that leads to this behavior:
char* In = "";
cin >> In;
Two things are wrong:
Your variable In does not have enough space for any non-empty string.
Even if it did, writing to that space would not be allowed.
To fix this issue you could either (1) switch to using std::string (recommended) or (2) change declarations of your C strings to character arrays, like this:
char In[128];