Locate the source of a bug with sscanf - c++

I've been struggling with this for too long.
Let's say i have this minimal code:
test.cxx
#include <iostream>
#include <cstdio>
int main (int argc, char *argv[])
{
const char *text = "1.01 foo";
float value = 0;
char other[8];
int code = sscanf(text, "%f %7s", &value, other);
std::cout << code << " | " << text << " | => | " << value << " | " << other << " | " << std::endl;
return 0;
}
$ g++ test.cxx; ./a.out produces this output, as expected:
$ 2 | 1.01 foo | => | 1.01 | foo |
Now I have these 5 lines embedded into a project with several thousand lines, and lots of includes ...
Compiling, running, and the output is now:
$ 2 | 1.01 foo | => | 1 | .01 |
What strategy could I use to locate the source of this inconsistency ?
EDIT:
export LC_ALL=C (or LC_NUMERIC=C); ./a.out seems to solve my problem

It might be caused by a different locale in your test and in your destination application. I was able to reproduce it on coliru:
by using:
setlocale(LC_ALL, "cs_CZ.utf8");
http://coliru.stacked-crooked.com/a/5a8f2ea7ac330d66
You can find some solutions in this SO:
sscanf() and locales. How does one really parse things like "3.14"?
[edit]
Solution with uselocale, but since you tagged this question with C++ then why not use std::stringstream and imbue it with proper locale (see link to SO above).
http://coliru.stacked-crooked.com/a/dc0fac7d2533d95c
const char *text = "1.01 foo";
float value = 0;
char other[8];
// set for testing, sscanf will assume floating point numbers use comma instead of dots
setlocale(LC_ALL, "cs_CZ.utf8");
// Temporarily use C locale (uses dot in floats) on current thread
locale_t locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
locale_t old_locale = uselocale(locale);
int code = sscanf(text, "%f %7s", &value, other);
std::cout << code << " | " << text << " | => | " << value << " | " << other << " | " << std::endl;
// Go back to original locale
uselocale(old_locale);
freelocale(locale);

Related

How to align output?

How to align the output?
I tried this
for(int x = 0; i<5; i++)
cout<<a[x]<<setw(5)<<"|"<<setw(5)<<b[x]<<endl;
If all of a have same char length then the output like this
frd | hehe
asd | hoho
.....
.....
But if not have same length
frd | hehe
asdfg | hohoo
How to solve this?
In your suggested code:
cout<<a[x]<<setw(5)<<"|"<<setw(5)<<b[x]<<endl;
you have two problems that are leading to misalignment. (1) you have not provided any width for a[x] so it will be output without any adjustment; and (2) depending on the alignment you seek, the default justification when a width is specified for std::cout will be right justified.
(additionally, as noted in my comment, in your first example, a[0] and a[1] cannot have the same length as the example suggests. There "frd " is stored with additional whitespace (or "asd\b" is stored with an embedded backspace) otherwise the output of "a[x]|" would be aligned.)
To provide alignment for the output of both a and b, you must specify, at minimum, the width of a[x] with std::setw(n). Further, unless you want a[x] aligned to the right of the field created by std::setw(5), you must control the justification by setting std::ios_base::fmtflags with std::setiosflags(std::ios_base::left) (or simply std::left). See std::setiosflags.
When you set a format flag for the stream, you are setting bits in a Bitmap type that will remain set after the current call to std::cout completes. So to tidy up after yourself and restore the flag state of the stream to default, you either (1) have to save the fmtflags for the stream with by capturing all flags with std::ios_base::fmtflags or (2) you must reset the individual flag you set with std::resetiosflags(...).
So if I understand your question and your request for alignment (though it is unclear how you want b[x] aligned), you could align both a and b with left justification by:
std::cout << "left justified output (both a & b)\n\n";
for (size_t i = 0; i < a.size(); i++)
std::cout << std::left << std::setw(5)
<< a[i] << " | " << b[i] << '\n';
or you could align a with left justification and then restore the default flag state letting b be output with default (right) justification, e.g.
std::cout << "\nleft justified output for a, default for b\n\n";
for (size_t i = 0; i < a.size(); i++)
std::cout << std::left << std::setw(5)
<< a[i] << " | " << std::resetiosflags(std::ios_base::left)
<< std::setw(5) << b[i] << '\n';
Putting that altogether in an example, you could do:
#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
int main (void) {
std::vector<std::string> a = { "frd", "asdfg", "asd", "quack" },
b = { "hehe", "hohoo", "haloo", "hack" };
std::cout << "left justified output (both a & b)\n\n";
for (size_t i = 0; i < a.size(); i++)
std::cout << std::left << std::setw(5)
<< a[i] << " | " << b[i] << '\n';
std::cout << "\nleft justified output for a, default for b\n\n";
for (size_t i = 0; i < a.size(); i++)
std::cout << std::left << std::setw(5)
<< a[i] << " | " << std::resetiosflags(std::ios_base::left)
<< std::setw(5) << b[i] << '\n';
}
Example Use/Output
$ ./bin/setwstring
left justified output (both a & b)
frd | hehe
asdfg | hohoo
asd | haloo
quack | hack
left justified output for a, default for b
frd | hehe
asdfg | hohoo
asd | haloo
quack | hack
Note: if you want to make multiple changes to flags within the course of an output operation and then restore ALL format flags to their original state, you can use:
std::ios_base::fmtflags f = std::cout.flags (); // save ios_base flags
// do output, set flags as desired
std::cout.flags (f); // restore saved flags
Let me know if this addresses the alignment you were attempting to achieve.
You can change the setw(#) with any number you need.
#include<iostream>
#include<iomanip>
#include<string>
using namespace std;
int main()
{
string a[5] = {"afdfadsf","ggrggeee","fdsafsda","erererefdsfd","sdfdsfdffdf"};
string b[5] = {"fdsfdsfd", "fdsfdsaffdf","fdsfsadfdfd","rererrefdfd","zzzzzzzfdfd"};
for(int i = 0; i<5; i++)
cout << left << setw(15) << a[i] << left << setw(15) << b[i] << endl;
}
Try using printf. Seriously, it works.
eg:
#include <cstdio>
int main() {
printf("%-10s | %10s\n", "asd", "asdad");
printf("%-10s | %10s\n", "asd", "adad");
printf("%-10s | %10s\n", "adsada", "adad");
printf("%-10s | %10s\n", "addasda", "adad");
printf("%-10s | %10s\n", "asdsd", "dad");
printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n", "asdsd", "dad");
printf("%-10s | %-10s\n", "asd", "asdad");
printf("%-10s | %-10s\n", "asd", "adad");
printf("%-10s | %-10s\n", "adsada", "adad");
printf("%-10s | %-10s\n", "addasda", "adad");
printf("%-10s | %-10s\n", "asdsd", "dad");
}
Gives
asd | asdad
asd | adad
adsada | adad
addasda | adad
asdsd | dad
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
asd | asdad
asd | adad
adsada | adad
addasda | adad
asdsd | dad

Why does std / boost::format cause this c_str() behaviour?

I'm using boost::format (not std:: as I'm using c++98) to format a string that I'm passing to a system() call.
When getting the c_str() of the string created by format, it seems to terminate halfway along the string. The same sting created with the literal value does not have the same problem. What's going on here?
Using Boost 1.46.1 according to BOOST_VERSION.
#include <boost/format.hpp>
#include <iostream>
#include <string>
int main(int argc, char** argv)
{
const std::string my_str = "echo '/%1%/ some other stuff'";
boost::format fmtr(my_str);
fmtr % "sleep 3"; // should read: echo '/sleep 3/ some other stuff'
std::cout << "1: " << fmtr.str() << "\n"; // 1. echo '/sleep 3/ some other stuff' (OK)
std::cout << "2: " << fmtr.str().c_str() << "\n"; // 2. echo '/sleep 3 (BAD)
// Try the c_str of a string not created through boost::format
const std::string finished = "echo '/sleep 3/ some other stuff'";
std::cout << "3: " << finished.c_str() << "\n"; // 3. echo '/sleep 3/ some other stuff' (OK)
// Try copying the string from format to see if that makes any difference (it doesn't)
std::string copy = fmtr.str();
std::cout << "4: " << copy.c_str() << "\n"; // 4. echo '/sleep 3 (BAD)
return 0;
}
Passing the c_str() to my system() call is resulting in the error:
sh -c: line 0: unexpected EOF while looking for matching `''
Presumably because it is finishing halfway along the string as well.
With proper includes your program works fine: ideone
#include <boost/format.hpp>
#include <iostream>
#include <string>
int main()
{
const std::string my_str = "echo '/%1%/ some other stuff'";
boost::format fmtr(my_str);
fmtr % "sleep 3"; // should read: echo '/sleep 3/ some other stuff'
std::cout << "1: " << fmtr.str() << "\n"; // 1. echo '/sleep 3/ some other stuff' (OK)
std::cout << "2: " << fmtr.str().c_str() << "\n"; // 2. echo '/sleep 3 (BAD)
// Try the c_str of a string not created through boost::format
const std::string finished = "echo '/sleep 3/ some other stuff'";
std::cout << "3: " << finished.c_str() << "\n"; // 3. echo '/sleep 3/ some other stuff' (OK)
// Try copying the string from format to see if that makes any difference (it doesn't)
std::string copy = fmtr.str();
std::cout << "4: " << copy.c_str() << "\n"; // 4. echo '/sleep 3 (BAD)
}
You should fix includes and return type of main and try again. If wrong behavior persist most probably you have broken version of c++ and/or boost library.

char concat to string returns wrong length

simple c++ program that adds a char byte to a string. The resulting length is wrong in the output.
#include <iostream>
#include <string>
int main(){
char x = 0x01;
std::string test;
test = x+"test";
std::cout << "length: " << test.length() << std::endl;
std::cout << "test: " << test << std::endl;
return 0;
}
the output:
length: 3
test: est
I am prepending a type byte to the string because I am going to be sending this data through a socket and the other side has a factory that needs to know the type of object to create.
1 + "test" = "est" // 1 offset from test
So you are getting the correct answer.
+---+---+---+---+---+
| t | e | s | t | \0|
+---+---+---+---+---+
+0 +1 +2 +3 +4
What you want is possibly:
std::string test;
test += x;
test += "test";
You are not concatenating a char with a std::string as you think you are. This is because "test" is actually a literal const char*, so you are just doing pointer arithmetic when you add x to it. You can replace
test = x + "test";
with
test = std::to_string(x) + "test";
Then your output will be
length: 5
test: 1test

Save Int Data into Text File in C++

I working on saving Data into text file and compare it with another text file. Below is the code I worked on:
ofstream outfile;
outfile.open("Data",ios::out | ios :: binary);
for(x=0; x<100; x++)
{
printf("data- %x\n", *(((int*)pImagePool)+x));
int data = *(((int*)pImagePool)+x);
//outfile<<(reinterpret_cast<int *>(data))<<endl;
outfile<<(int *)data<<endl;
}
The result from printf is 24011800 and result read from text file is 0x24011800
Why there is 0x appeared? Do we able to remove it?
What is the difference between reinterpret_cast<int *> & (int *) but both giving the same result?
It's because you cast it as a pointer, so the output will be a pointer.
Since data is a normal value variable, just write it as usual:
outfile << data << '\n';
I also recommend you stop using printf when programming C++, there no reason to use it. Instead output using std::cout:
std::cout << "data- " << *(((int*)pImagePool)+x) << '\n';
Or if you want hexadecimal output
std::cout << "data- " << std::hex << *(((int*)pImagePool)+x) << '\n';
"%x" is a specifier for a hexadecimal number. Check this table: http://www.cplusplus.com/reference/cstdio/printf/
Use "%d" to output a decimal.
EDIT: About the casting, see this:
Reinterpret_cast vs. C-style cast
This is a very simple example using the ofstream f. The most complicated part are the parameters passed to the open, specifically std::ios::out which specifies the file direction. You could also use std::ios:in for reading from a file along with cin.
// ex5.cpp
#include <string>
#include <iostream>
#include <fstream>
#include "hr_time.hpp"
#include >ios>
int main(int argc, char * argv[])
{
CStopWatch sw;
sw.startTimer() ;
std::ofstream f;
f.open("test.txt",std::ios::out ) ;
for (int i=0;i<100000;i++)
{
f << "A very long string that is number " << i << std::endl;
}
f.close() ;
sw.stopTimer() ;
std::cout << "This took " << sw.getElapsedTime() << " seconds" << std::endl;
return 0;
}

C++ Escape Character and Reference Variables Output Confusion

So these are the type of examples that make me frustrated because they seem simple, but do not produce the desired result. Consider the example below:
#include <iostream>
int main()
{
int a = 7;
int &b = a;
std::cout << "a = " << a << " ,\tb = " << b << std::endl;
b = 10;
std::cout << "a = " << a << " ,\tb = " << b << std::endl;
}
Output:
a = 7 , b = 7
a = 10 , b = 10
Can someone please explain to me why the first escape character seems to be ignored and there is no tab, but in the second example the tab is present. Been looking at this example for a while and am no closer to a solution.
Note: I am running this in Visual Studios 2010
"a = 7 ," has 7 characters. If there is a tab stop at position 8 (e.g. as set by the tabs command for terminals), appending a tab character effectivly adds the same amount of whitespace as appending a space character.