I'm trying to read in a .csv file filled with floats. I used this to build my code. However, the data reads in correctly but is read in as a string but I want to use the data as floats. If I try to use stof(string) I get an error that it is trying to convert a non number to a number. So I went the really long way and converted the string to a char and that to a float, which works but is VERY ugly. However, once all the data is read in and is printed out with a cout the program my crashes
trackBarFile.open("test2.csv");
std::string line, line2, line3;
int count;
std::string token;
float tokenNum,lineFloat,line2Float,line3Float;
char cstr[5],cstr2[5];
while (getline(trackBarFile, line,','))
{
cstr[line.size()+1];
strcpy(cstr, line.c_str());
lineFloat = atof(cstr);
getline(trackBarFile, line2,',');
cstr[line2.size()+1];
strcpy(cstr, line2.c_str());
line2Float = atof(cstr);
getline(trackBarFile, line3);
cstr2[line3.size()+1];
strcpy(cstr2, line3.c_str());
line3Float = atof(cstr2);
std::cout<<line<<","<<lineFloat<<" , "<<line2<<","<<line2Float<<" , "<<line3<<","<<line3Float<<std::endl;
}
trackBarFile.close();
It seems I have stumbled upon the answer to my own question. Thanks to the above questions I started looking for different ways to convert the string to a float. The +2 in the print out can be ignored, was my "pinch" to make sure I wasn't dreaming
trackBarFile.open("TrackBarSignal.csv");
std::ofstream fout;
fout.open("Output_ReadInCSV.txt");
std::string line, line2, line3;
int count;
float tokenNum,lineFloat,line2Float,line3Float;
while (getline(trackBarFile, line,',')&&getline(trackBarFile, line2,',')&&getline(trackBarFile, line3))
{
lineFloat = (float)atof(line.c_str());
line2Float = (float)atof(line2.c_str());
line3Float = (float)atof(line3.c_str());
std::cout<<line<<","<<lineFloat+2<<" , "<<line2<<","<<line2Float+2<<" , "<<line3<<","<<line3Float+2<<std::endl;
}
trackBarFile.close();
Related
I have this string in my C++ GNU ARM embedded system:
char* TempStr = "pressure 0.85";
I need the number value stored as a separate float variable called presmax.
Up until now the number to be parsed has always been an integer, so I could use sscanf without any issues. However, as I have read about extensively on the web (and experienced first hand), sscanf doesn't typically work on floats in embedded systems (without some extensive configuration/loss of flash space).
I'm wondering if anyone has any suggestions. Perhaps I could parse the "0.85" as a char array? I'm not quite sure how to do that, though it would allow me to use atof() to turn it into a float, as I've done elsewhere in the program.
I realize the other option is to write a function, however I'm quite an amateur programmer so if there's a more robust/time effective solution I'd best take it.
UPDATE:
In case it helps, TempStr is a string copied from a .txt file on an SD card using FatFs. Here's the full code that reads two lines and stores the results in TempStr each time. I parse the string into its respective variable each time TempStr is stored:
FILINFO fno;
FIL fsrc;
int FileEnd = 0;
int CurrentLine = 0;
int pressmax = 0;
int timemax = 0;
char* TempStr;
WCHAR CharBuffer[100];
res = f_stat("config.txt", &fno); //check for config.txt file
res = f_open(&fsrc, "config.txt", FA_READ | FA_OPEN_ALWAYS); //open config.txt file
//first line
TempStr = f_gets((char*)CharBuffer, sizeof(fsrc), &fsrc);
CurrentLine ++;
FileEnd = FileEnd + strlen(TempStr) + 1;
//sscanf(TempStr, "%*s %i", &presmax); //what I did when presmax was an int
//second line
while ((f_eof(&fsrc) == 0)){
TempStr = f_gets((char*)CharBuffer, sizeof(fsrc), &fsrc);
CurrentLine ++;
FileEnd = FileEnd + strlen(TempStr) + 1;
}
//sscanf(TempStr, "%*s %i", &timemax);
Using GNU ARM Build tools on an STM32L w/Eclipse.
If you are guaranteed that your input will be in the form of
text floating_point_number
then once you have TempStr you can advance a pointer through it until you reach the space, and then go one position further to get to the floating point part of the string. Then you pass that pointer to atof to get the value out of the remainder of string. That would look like
char* fp = TempStr;
while (*fp != ' ') ++fp; // get to the space
double value = atof(++fp); // advance to floating point part and pass to atof
If you don't need TempStr after you get the value then you can get rid of fp and just use
while (*TempStr != ' ') ++TempStr ; // get to the space
double value = atof(++TempStr); // advance to floating point part and pass to atof
It can be done as follows:
float presmax = (float)atof( strchr( TempStr, ' ' ) ;
The cast is only necessary because your question specifically asks for float and atof() returns a double. The cast would be implicit in any event, so:
float presmax = atof( strchr( TempStr, ' ' ) ;
is also acceptable.
strchr() returns a pointer to the first space character, and atof() ignores any leading space. If your config file might use a TAB character, then:
float presmax = (float)atof( strpbrk( TempStr, " \t" ) ;
It will fail if either strchr() or strpbrk() return NULL when the delimiter is not found, so you might make it more robust thus:
#define PRESMAX_DEFAULT 1.0f
const char* prestr = strchr( TempStr ) ;
float presmax = prestr == NULL ? PRESMAX_DEFAULT : (float)atof( prestr ) ;
I am writing a program which reads input from a text file and converts it to hexadecimal for later processing.
ifstream fin("input.txt"); //open file with ifstream
if(fin.is_open()){ //check if file is open
for(int i = 0; i<length; i++){ //int length for how many characters I need
fin.get(buffer[i]); //write into char array buffer[256]
}
}
else{
cout<<"Can't open file";
exit(0);
}
fin.close();
So everything is fine, it opens up nicely and gets exactly as many characters as I need from there, later I use a function to turn that into a hexadecimal string:
std::string string_to_hex(const std::string input)
{
static const char* const lut = "0123456789ABCDEF";
size_t len = input.length();
string output;
output.reserve(2 * len);
for (size_t i = 0; i < len; ++i)
{
const unsigned char c = input[i];
output.push_back(lut[c >> 4]);
output.push_back(lut[c & 15]);
}
return output;
}
which also works fine, it gives me the correct hexadecimal value for the characters that I get.
Now here is the problem: my file contains null characters (hexadecimal "00" characters aka '\0') which I need to read into my program and do a proper conversion so every null character in my array after conversion should look like "00". Every time I
try to convert null characters in my array they change into spaces (hexadecimal "20"), which ruins my data for processing later. Changing "20" into "00" is also not an option since the file contains real spaces that also need to be properly processed.
This is my first time working with null characters and I am absolutely confused on how to properly process them. All I know is that null characters are used at the end of a string or an array so when I print them out the program would know when to stop.
I do not know how I should do it properly. I tried opening the file differently using fopen, I tried copying my input.txt into an array differently. Maybe it copies it properly but the hex conversion doesn't work. Maybe I shouldn't send it as a string for conversion. I don't know. I also noticed that when I tried to copy paste a sample from the file to another file, all the null characters have been replaced by spaces, maybe it has something to do with this?
I want to read the 3rd line from a text file in as a string, convert it to a long long int, and return that value.
The data on the 3rd line of the text file is 1234567890123456
long long int File::Getline3(int user1, int user3)
{
std::string filename = std::to_string(user1);
std::ifstream fin(filename + ".txt");
fin.getline (line1, 5);
fin.getline (line2, 5);
fin.getline (line3, 20);
fin.close();
// convert line 3 to a string called str
const char *line3;
std::string str(line3);
// convert str to long long int called user3
long long int strtoll(const char *nptr, char **endptr, int base);
char* endptr = NULL;
user3 = strtoll(str.c_str(), &endptr, 10);
return user3;
}
The comments are in to show what I think I'm doing, however I am probably wrong (I'm new to pointers).
I get an "unresolved external" error when I try to build my program.
long long int strtoll(const char *nptr, char **endptr, int base);
This line declares a function. It means that when you call strtoll a few lines down, you're going to be calling that function as it's the most obvious candidate. However, you never defined it.
Instead you meant to call std::strtoll, which is defined (by the standard library), and which will be found through your presumed using namespace std directive if you do not hide it by falsely declaring this non-existent function of your own with the same name. :)
Simply remove the excess declaration:
// convert str to long long int called user3
char* endptr = NULL;
user3 = strtoll(str.c_str(), &endptr, 10);
You have a similar issue with your const char* line3, which you declare inside the function, never assign anything to, then construct a string out of. That's undefined; the pointer is uninitialised. Assuming you have some line3 data member (along with your line1 and line2), again you're hiding it with a local variable of the same name.
Finally, passing user3 in by value is utterly pointless if you're just writing to it and returning it. Remove that parameter.
Putting all this together, your code should probably look like:
// convert line3 to long long int
char* endptr = NULL;
return strtoll(line3, &endptr, 10);
In short, be less declaration-happy!
https://connect.microsoft.com/VisualStudio/feedback/details/758053/missing-strtold-strtoll-strtoull-functions-from-stdlib-h
A work around for Visual C++ that does not have these included.
long long int File::Getline3(int user1)
{
std::string filename = std::to_string(user1);
std::ifstream fin(filename + ".txt");
std::string line1, line2; // place to actually store the lines
getline(fin, line1); // read a line
getline(fin, line2); // read another line
long long int number_on_line_3; // somewhere to store the number
fin >> number_on_line3; // store the number
fin.close();
return number_on_line_3; // return the number
}
I'm reading data from a file and trying to display the raw data as 2 digit hex strings.
I'm using the Qt framework, specifically the QTextEdit.
I've tried a bunch of different approaches and have almost accomplished what I want it to do, however it has some unexpected errors I don't know anything about.
Currently this is my implementation:
1) Read in the data:
ifstream file (filePath, ios::in|ios::binary|ios::ate);
if (file.is_open())
{
size = file.tellg();
memblock = new char [size+1];
file.seekg(0, ios::beg);
file.read(memblock, size);
file.close();
}
2) Create a single QString that will be used (because QTextEdit requires a QString):
QString s;
3) Loop through the array appending each successive character to the QString s.
int count = 0;
for(i=0;i<size;i++)
{
count++;;
s.append(QString::number(memblock[i], 16).toUpper());
s.append("\t");
if (count == 16)
{
s.append("\n");
count -= 16;
}
}
Now this works fine, except when it reaches a character FF, it appears as FFFFFFFFFFFFFFFF
So my main questions are:
Why do only the 'FF' characters appear as 'FFFFFFFFFFFFFFFF' instead?
Is there a way to convert the char data to base 16 strings without using QString::number?
I want this implementation to be as fast as possible, so if something like sprintf could work, please let me know, as I would guess that might be faster that QString::number.
QString can't be used for binary data. You should use QByteArray instead. It can be easily created from char* buffer and can be easily converted to hex string using toHex.
QByteArray array(memblock, size);
textEdit->setText(QString(array.toHex()));
QString::number doesn't have an overload that takes a char, so your input is being promoted to an int; consequently you're seeing the effects of sign extension. You should be seeing similar behavior for any input greater than 0x7F.
Try casting the data prior to calling the function.
s.append(QString::number(static_cast<unsigned char>(memblock[i]), 16).toUpper());
I am relatively new to c++ programming and I have hit one of my first major snags in all of this..
I am trying to figure out how to read a value/character from a generic ".txt" file that is on notepad. With that comparison I want to determine whether or not to read that entire line, but I can't seem to just read the single one or two digit number, I got it to read the whole line using { 'buffername'.getline(variable, size) } but when I try to change the 'size' to a specific number it gives me a comparison error saying that its invalid to switch to 'int' or 'char' (depending on how I declare the variable).
Any help is appreciated.
Thanks
int length = 2;
char * buffer;
ifstream is;
is.open ("test.txt", ios::binary );
// allocate memory:
buffer = new char [length];
// read 2 char
is.read (buffer,length);
//Compare the character and decide
delete[] buffer;
return 0;
You'll want to use an ifstream to get the value (ref 1).
Something like the following should work. Here I use a word of type std::string, but you can replace that with other types to read them (ie: int, double, etc...).
std::ifstream f("somefile.txt");
std::string word;
std::string line;
if(f >> word){
if(<the comparison>){
line = f.getline();
}
}
Here's an extended example of how to use the ifstream
First of all, for performance reasons it is a bad idea to read 1 byte at a time.
I suggest this alternative:
You would be better off reading in the whole line, and then using character array.
char variable[1000];
read your line in from the file into variable.
if (variable[1]=='c') { printf("Byte 2 (remember 0 offset) is compared for the letter c";}
getting a 2 digit #
number=((variable[3]-48)*10)+(variable[4]-48);
You have to subtract 48 because in ASCII the number 0 is 48.