I am using C++ and writing a program that is supposed to do a bunch of stuff with primes. However the main issue is that I am having trouble converting in between ints and strings. I believe the following is the relevant code:
for(int j=0;j<size-1;j++){
num=primes[j];
ss<<num;
ss>>temp;
ss.str("");
for (int count=0; count < temp.size(); count++) {
cout<<temp<<endl;
}
I know that I could Google and figure out how to convert from an integer another way. However, I have a feeling that the reason I can't figure out what is going wrong is because I'm lacking some fundamental knowledge about stringstreams which I'm not aware of which I'm hoping can be fixed. num is an int and ss is a stringstream and cout temp is printing out 2 every single time, which is the value of primes[0]. I think the stringstream might be not reading after the first trial because of something to do with a newline character but I don't really know.
The reason for what you are experiencing is that the EOF_BIT will be set in ss after reading the first value into temp, after that no read/writes can be made to the std::stringstream and therefore temp is not updated with a new value.
A more human readable way of explaining the above; the std::stringstream ss will think that it has reached the end (which it has, at one point). You'll need to tell it to "start all over again" (reset all error-flags) for it to be usable in another iteration.
How do I solve this issue?
There are a few methods available, to me the most clear (in code readability) is to use a new std::stringstream for each iterator in your loop (see "Example solution #2).
Check out the snippets below that all will output:
2
3
5
7
11
13
17
Example solution #1
int const PRIMES_SIZE = 7;
int const primes[PRIMES_SIZE] = {2,3,5,7,11,13,17};
std::stringstream ss;
std::string temp;
for (int i =0; i < PRIMES_SIZE; ++i) {
ss << primes[i];
ss >> temp;
std::cout << temp << std::endl;
ss.clear (); // unset error flags
}
Example solution #2
int const PRIMES_SIZE = 7;
int const primes[PRIMES_SIZE] = {2,3,5,7,11,13,17};
for (int i =0; i < PRIMES_SIZE; ++i) {
std::stringstream ss;
ss << primes[i];
std::cout << ss.str () << std::endl;
}
Example solution #3
#include <iterator>
...
int const PRIMES_SIZE = 7;
int const primes[PRIMES_SIZE] = {2,3,5,7,11,13,17};
std::stringstream ss;
std::copy (primes, primes+PRIMES_SIZE, std::ostream_iterator<int> (ss, "\n"));
std::cout << ss.str ();
Related
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.
I've tried a bunch of methods listed on here but none of them work. It's always waiting for more input.
I've tried while(std::getline(std::cin, line)) and the method below, nothing seems to work:
#include <iostream>
#include <sstream>
using namespace std;
int main(){
long length = 1UL<<32;
int array[length];
// memset(array, 0, (length-1) * sizeof(int));
for(int i = 0; i < length; i++)
array[i] = 0;
string line;
int num;
while(!cin.eof()){
getline(cin,line);
stringstream ss(line);
ss >>num;
array[num]++;
}
for(int i = 0; i < length; i++)
if(array[i]){
cout << i << ": ";
cout << array[i] << endl;
}
}
First off, do not use std::cin.eof() to control your loop! It doesn't work. Also, you always need to check for successful input after the input.
That said, to terminate the input you'll need to enter the appropriate end of file character, probably at the start of the line (how it works entirely somewhat depends on the system, some settings, etc.). On Windows you'd use Ctrl-Z, on UNIXes you'd use Ctrl-D.
First off, this part of your program attempts to allocate 4 GB of memory on the stack, which doesn't work on my machine (good luck finding any machine with 4 GB of continuous memory space):
long length = 1UL<<32;
int array[length];
If I change that to a much more reasonable:
long length = 32;
Then it works fine for me:
$ g++ -g test.cpp -o test && ./test
2
5
# pressed control+d
2: 1
5: 2
$
So I'm guessing something else is wrong.
Note: Unless you actually plan to use all of those indexes, you may want to considering using an unordered_map, so you only use the space you actually need.
The condition you are looking for can be most easily tested by evaluating "std::cin" as a bool, i.e. while (cin). But it won't do this until you have tried to read beyond EOF, so expect an empty getline:
#include <iostream>
#include <string>
int main() {
std::string input;
while (std::cin) {
std::cout << "Type something in:\n";
std::getline(std::cin, input);
if(input.empty())
continue;
std::cout << "You typed [" << input << "]\n";
}
std::cout << "Our work here is done.\n";
return 0;
}
Live demo: http://ideone.com/QR9fpM
I am quite new in c++ and programming so sorry in advance in my question repeats. I have a text file of 3 lines:
7
00000000000000000000000*0000
0 0 0 R 0
What I need to do is read 2nd line and write it into an array as char. But I must not include 3rd line because it will go to a completely different matrix. My code so far :
ifstream input;
input.open("input1.txt");
input >> start;
char a=0;
string line;
while (getline(input, line))
{
a=0;
istringstream iss(line);
int length = line.size();
for (int i=0; i<length; i++)
{
iss >> a;
A[i] = a;
cout << A[i] << " " << i << endl;
}
}
input.close();
However, with this code it always starts new array for 3rd line. What am I doing wrong? What is the easiest way to fix it? Thank you.
-----------------------------Update--------------------------------------
I have modified the code but it still does not work properly. I am getting this kind of result : 5)-└ instead of correct one. My current code:
void Read(int &numLines, int &start, vector<char>&A, char B[][5])
{
ifstream input;
input.open("input.txt");
input >> start;
input.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
string line;
if(getline(input, line))
{
for(char temp: line)
{
A.push_back(temp);
}
}
input.close();
}
A here is a vector I want to write 2nd line to, char by char
Start is just an integer in which I am storing 1st line (7)
Thank you very much for advices
Mixing >> and std::getline is non-trivial. For example, after input >> start; the end of line marker is left in the stream in case it's still needed. In your case it isn't, and it is picked off by the subsequent call to getline, resulting in a read of an empty line.
This is what's complicating your read of line and forcing the while loop and test for empty lines.
Step through your program with your development environment's debugger and you'll see what I'm talking about. Get used to using the debugger. It's possibly the best programming productivity tool you'll ever encounter.
The easiest way to fix it is to place
input.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
after
input >> start;
to eat up the end of the line (and anything else that might be on that line. This needs the addition of #include<limits> to get std::numeric_limits<std::streamsize>::max.
Then you can remove the while loop and replace it with
if (getline(input, line))
No loop, not chance of consuming multiple lines from the file. And the logic for reading and processing the third line can follow.
Side note: instead of that for loop, consider
int i = 0;
while (iss >> a)
{
A[i] = a;
cout << A[i] << " " << i << endl;
i++;
}
This will march through iss until it hits the end of the line. You can also throw iss out entirely and just read the characters directly out of line.
int i = 0;
for(char temp: line)
{
A[i] = temp;
}
And A should probably be a vector if it isn't already to reduce the chances of buffer overruns.
for(char temp: line)
{
A.push_back(temp);
}
I would go with something like this:
std::string start;
std::string Astring;
ifstream input;
input.open("input.txt");
input >> start;
input >> Astring;
// If you really want a char array
char * A = new char[Astring.size()];
for (unsigned int i = 0; i < Astring.size(); i++) {
A[i] = Astring[i];
}
// Don't forget to delete after use
delete[] A;
Moreover, if you just need the char array as an input to something else later, you can call Astring.c_str() instead of that for loop, which returns a C-style char array.
I'm kind of new with programming and I have wired problem.
I tried to search and read about it, but without success.
I have main file and one class (on windows)
main:
main()
{
LogOut x();
x.WriteToDelayFile(1.2, 3);
}
LogOut class:
void LogOut::WriteToDelayFile(double simTime, int nodeNum)
{
string fileName = "Delay" + nodeNum;
FILE* pFile = OpenFile(fileName);
fputs ("something\n",pFile);
}
I can't figure it out but when I call to WriteToDelayFile(2, 3) with values, I get garbage values edit: (for example, on debug- nodeNum=321546 instead of nodeNum=3) on the LogOut::WriteToDelayFile(double simTime, int nodeNum) implementation
Why does it happen?
Thanks.
As user657267 pointed out in his comment, you may not concatenate a string literal and an int string fileName = "Delay" + nodeNum;. Here you are getting a pointer into the literal, that may even be out of range:
string s = "hello"+1; // leads to "ello" in s
The probably intended concatenation can be done using a stringstream:
#include <sstream>
#include <assert>
void concat_check()
{
std::stringstream ss;
ss << "hello" << 1;
assert(ss.str() == "hello1");
}
Wolf you are a little bit wrong
string s = "hello"+3;
gives "lo" in s data
and
string si = string("hello")+3;
is incorrect you need to use stringstream instead
std::stringstream ss;
ss << "hello" << 3;
std::string s = ss.str();
Dudi Reuveni how can you tell that nodeNum has wrong data?
I'm trying to create a replacement for sprintfs' %05d behavior. Althought, I've found a similar question here on stackoverflow, the proposed solution there doesn't work for me when I'm testing with negative numbers.
Doing a "sprintf(buf, "%05d", -12)", I'm getting "-0012" back which looks nice.
Using stringstream, width and fill, I'm getting "00-12" which seams reasonable when looking at the docs from std::basic_ios::fill
The fill character is the character used by output insertion functions to fill spaces when padding results to the field width.
but doesn't look like something one could wish.
So I'm confused and don't know if I'm doing something obvious wrong or if width/fill from the std streams doesn't easily support this situation.
A compilable testcode can be found on codepad.
Here's an extract of the stream based conversion:
std::string NumberToString(const long iVal, const int iNumDigit)
{
std::stringstream ss;
if (iNumDigit >= 0) ss.fill(' ');
else if (iNumDigit < 0) ss.fill('0');
ss.width(std::abs(iNumDigit));
ss << iVal;
return ss.str();
}
EDIT1: Solution:
To match the std stream approach with printf formatting for %05d, jrok's solution can be used for the case with leading zeros. Here's the new function:
std::string NumberToString(const long iVal, const int iNumDigit)
{
std::stringstream ss;
if (iNumDigit >= 0) ss.fill(' ');
else if (iNumDigit < 0) { ss.fill('0'); ss.setf(std::ios::internal, std::ios::adjustfield); }
ss.width(std::abs(iNumDigit));
ss << iVal;
return ss.str();
}
Use stream manipulator std::internal.
It (along with std::left and std::right) lets you specify where the fill characters go. For example
std::cout << std::setw(5) << std::setfill('0') << std::internal << -1;
will print -0001.