I'm quite new to C++, but I'm used to some coding with R language. I started, a few weeks ago, to put together a small application that should copy and rename file pairs (.seq/.ab1). Result from a DNA sequencer analysis (renaming hundreds of them manually would be a real time waste, specially because we have lists with their new names).
Everything seemed to be fine, but the new files (those copied) appear with a "special character" in their names (right before the file type), it seeems like a space, but its not (I've replaced it with a space, and the file opened correctly). After deleting it the file can be oppened by its associated application, but with it, the aplication acusses the file to be corrupted.
The issue seems to come from the code related to ostringstream::str member function, but I honestly don't know how to fix it. I wonder if its not inserting a null character there, before I append the file type...
Here is the part of the code responsible. It gets the old and new names from a 2 column csv file, data separated by ";". Original data, and new (renamed files) data are kept in diferent directories, thats the reason I need to create a string with each file path inside a for loop. I intend to check old and new files content later, probably with memcmp. But first I need them to be correctly renamed.
I'm on a Ubuntu 14.04 (64 bit) machine with gcc 4.8.4 as compiler. I already excuse myself for the probably poor coding and bad english, I'm not a native speaker (writer, actually).
fNew.open(filename);
std::ostringstream oldSeqName (std::ostringstream::ate);
std::ostringstream newSeqName (std::ostringstream::ate);
std::ostringstream oldAb1Name (std::ostringstream::ate);
std::ostringstream newAb1Name (std::ostringstream::ate);
std::fstream log;
time_t now = time(0);
for (std::string nOld, nNew; getline(fNew, nOld, ';') && getline(fNew, nNew); )
{
std::cout << "Old Name: " << nOld << " -> New Name: " << nNew << std::endl;
// Keep a log of the name changes
log.open("NameChangesLog.txt", std::fstream::out | std::fstream::app);
log << ctime(&now) << " - " << "Old Name: " << nOld << " -> New Name: " << nNew << std::endl;
log.close();
// Create old seq files paths string
oldSeqName.str(nOld);
oldSeqName << ".seq";
std::string osn = "./Seq/" + oldSeqName.str();
// Create new seq files paths string
newSeqName.str(nNew);
newSeqName << ".seq";
std::string nsn = "./renamed/" + newSeqName.str();
std::ifstream ifseq(osn, std::ios::binary);
std::ofstream ofseq(nsn, std::ios::binary);
ofseq << ifseq.rdbuf();
ifseq.close();
ofseq.close();
// Create old ab1 files paths string
oldAb1Name.str(nOld);
oldAb1Name << ".ab1";
std::string oan = "./Seq/" + oldAb1Name.str();
// Create new abq files paths string
newAb1Name.str(nNew);
newAb1Name << ".ab1";
std::string nan = "./renamed/" + newAb1Name.str();
std::ifstream ifab1(oan, std::ios::binary);
std::ofstream ofab1(nan, std::ios::binary);
ofab1 << ifab1.rdbuf();
ifab1.close();
ofab1.close();
}
fNew.close();
Is the list file prepared on Windows machine? In that case it would have DOS line ending (\r\n) and is not well suited for getline on Unix. The character you see is likely \r. Make sure you use dos2unix utility before feeding the list file to your program
You probably forget to trim the values returned from getline, so they may still contain whitespace. Whitespace may be tricky to pick up by the application.
Related
I've been trying to take a .txt document with three number entries, read those entries as strings and convert those entries in ints, then put them into an int array, but had no success in doing so and i have no clue as to why. Note that the entries as well as some variable names are pre determined by the assignment, additionally we have to use the std::stoi("string") command, which i am not familiar with nor has any syntax been provided to us (which is especially strange since we are usually not allowed to stray to far from the lecture material)
What I excpected to happen is that the numbers from the .txt file were converted into an array, however what actually happened is that an "unhandled exception" (my apologies if that term does not make sanes we have to programm in our native language) occured and the string library opened itself, marking the error on line 107. The problematic line in my code seems to be "auftraegearray[i++] = std::stoi(MengeanAuftraegen);"
int main()
{
std::fstream Auftraege;
Auftraege.open("Auftraege37.txt", std::ios::out);
Auftraege << "10" << std::endl;
Auftraege << "1" << std::endl;
Auftraege << "20" << std::endl;
Auftraege.close();
int i = 0;
int auftraegearray[4];
std::string MengeanAuftraegen;
Auftraege.open("Auftraege37.txt", std::ios::in);
while (!Auftraege.eof())
{
getline(Auftraege, MengeanAuftraegen);
std::cout << MengeanAuftraegen << std::endl;
auftraegearray[i++] = std::stoi(MengeanAuftraegen);
}
Auftraege.close();
I was thinking if it is possible to make a string in C++ which contains data in it like, I don't want to make a string of strings or an array of strings.
Suppose I have a string mv:
mv =
"hello
new
world "
"hello", "new" and "world" are in different lines. Now if we print mv, then "hello", "new" and "world" should come on different lines.
I was also thinking with respect to competitive programming. If I concatenate all the answers of queries in a single string and then output the answer, or cout all the queries one by one, will there be a time difference in both the outputs?
i want my string variable to store the information in this format therefore
like my string variable mv should have some strings in first line and some
strings on second line and this whole should work like a single string
What is a string (std::string) in C++?
It is a container for a dynamically resizable array of characters, equipped
with methods for manipulating that array.
An array of characters is:
characters: |c0|c1|c2|c3|...|cN|
That's the nature of an std::string. There's nothing you can do about that.
What is a line (of text)?
There is no formal definition of a line in C++, or any other programming
language. A line is a visual concept that belongs to reading and writing
text arranged in 2-dimensional space. One line is vertically above or below
another.
Computers don't arrange data in 2-dimensional space. They arrange it all in
linear, 1-dimensional, storage. No data is vertically above or below any other data.
But of course programming languages can represent lines of text and they
all do it by the same convention. Conventionally, a line is an array of
characters that ends with a new-line sequence.
A new-line sequence is itself an array of one or two characters, depending
on your operating system's convention. Windows uses the 2-character sequence
carriage-return,line-feed. Unix-like operating systems use the 1-character
sequence line-feed. You can study the subject in
Wikipedia: Newline. But for
portability, in C++ source code the newline sequence - whatever it actually is -
is represented by the escape sequence
\n, which you can use in source code as if it were a character.
So the array of characters:
|h|e|l|l|o|\n|
represents the line of text:
hello
in C++. And the array of characters:
|h|e|l|l|o|\n|n|e|w|\n|w|o|r|l|d|\n|
represents the three lines of text:
hello
new
world
And if you want to store that array in a single std::string, C++ lets you do it
like this:
std::string s0{'h','e','l','l','o','\n','n','e','w','\n','w','o','r','l','d','\n'};
or more conveniently like this:
std::string s1{"hello\nnew\nworld\n"};
or even - if you have a phobia about using the \n escape sequence - like this:
std::string s2
{R"(hello
new
world
)"};
All of these ways of storing the three lines in a string create exactly the
same character array in that string, namely:
|h|e|l|l|o|\n|n|e|w|\n|w|o|r|l|d|\n|
They all create exactly the same std::string.
And if you print any of those strings you will see the same thing, e.g.
this program:
#include <string>
#include <iostream>
int main() {
std::string s0{'h','e','l','l','o','\n','n','e','w','\n','w','o','r','l','d','\n'};
std::string s1{"hello\nnew\nworld\n"};
std::string s2 // Yes...
{R"(hello
new
world
)"}; // ...it is meant to be formatted like this
std::cout << "--------------" << std::endl;
std::cout << s0;
std::cout << "--------------" << std::endl;
std::cout << s1;
std::cout << "--------------" << std::endl;
std::cout << s2;
std::cout << "--------------" << std::endl;
return 0;
}
outputs:
--------------
hello
new
world
--------------
hello
new
world
--------------
hello
new
world
--------------
Live demo
If I haven't understood your question wrong.
Here is your answer, add an escape character at the end of each line.
string mv = "hello\n\
new\n\
world\n";
\n -> new line
\ -> escape character
Here is the working example:
Example
string mv = "hello\n\
new\n\
world\n";
You can just add the \n character to the string to create a new line.
cout << "Hello \n New \n World" << endl;
This will output:
Hello
New
World
let me first thank you for taking the time to read this.
I'm trying to read a file in c++. Currently I have a method that allows the user to select a file in explorer and returns this as an 'std::string'. I then have to open this file, but the method I have for this uses const char*. Therefore I need to convert from one to the other.
If there is an easy method in windows for reading a file using a string instead then let me know as it would solve my entire problem.
When I convert from string to const char*, using str.c_str(), I get a lot of weird characters at the end. I've researched other topics with the same problem, but the answers all seem very specific for those projects, or say just stick to sting/vector instead. Obviously I would happily do this, but I don't have a method that opens the file using a string/vector.
Any help is appreciated :) The code and output of where this occurs is pasted below.
*SOURCE
std::string f;
if (LOWORD(wParam) == 1) {
f = openFile();
char *fchar = new char[f.size()+1]; // +1 to account for \0 byte
//char *fchar = std::vector[1];
std::strncpy(fchar, f.c_str(), f.size());
file1 = fchar;
std::cout<<"string size: " << f.size() << std::endl;
std::cout<<"string: " << f << std::endl;
std::cout<<"fchar: " << fchar << std::endl;
std::cout<<"file1: " << file1 << std::endl;
}
OUTPUT
string size: 33
string: C:\Users\Joseph\Pictures\back_raw
fchar: C:\Users\Joseph\Pictures\back_raw═²²²²½½½½½½½½¯■
file1: C:\Users\Joseph\Pictures\back_raw═²²²²½½½½½½½½¯■**
std::strncpy() does not place a `\0' character at the end of the string. See http://www.cplusplus.com/reference/clibrary/cstring/strncpy/. You need to copy that as well:
std::strncpy(fchar, f.c_str(), f.size() + 1);
Where is file1 declared ?
What about openFile ? (would like to know its return type)
Could you try to manually put that '\0' ? IMHO, your char* is simply lacking the \0 at the end...
Make sure you put a \0 at the end, everywhere you need to.
I created a binary file using a c++ program using protocol buffers. I had issues reading the binary file in my C# program, so I decided to write a small c++ program to test the reading.
My proto file is as follows
message TradeMessage {
required double timestamp = 1;
required string ric_code = 2;
required double price = 3;
required int64 size = 4;
required int64 AccumulatedVolume = 5;
}
When writing to protocol buffer, I first write the object type, then object length and the object itself.
coded_output->WriteLittleEndian32((int) ObjectType_Trade);
coded_output->WriteLittleEndian32(trade.ByteSize());
trade.SerializeToCodedStream(coded_output);
Now, when I am trying to read the same file in my c++ program i see strange behavior.
My reading code is as follows:
coded_input->ReadLittleEndian32(&objtype);
coded_input->ReadLittleEndian32(&objlen);
tMsg.ParseFromCodedStream(coded_input);
cout << "Expected Size = " << objlen << endl;
cout<<" Trade message received for: "<< tMsg.ric_code() << endl;
cout << "TradeMessage Size = " << tMsg.ByteSize() << endl;
In this case, i get following output
Expected Size = 33
Trade message received for: .CSAP0104
TradeMessage Size = 42
When I write to file, I write trade.ByteSize() as 33 bytes, but when I read the same object, the object ByteSize() is 42 bytes, which affects the rest of the data. I am not sure what is wrong in this. Please advice.
Regards,
Alok
This is guesswork, based on the above: when you use ParseFromCodedStream, you aren't actually limiting that to the objlen that you previously found; thus, if the stream contains any more data than this (i.e. that isn't the end of the file), the engine will try to keep reading to the EOF. You must cap the length to your expectation. I am not a C++ expert, so I can't offer direct guidance, but if this was C# (using protobuf-net):
objType = ProtoReader.DirectReadLittleEndianInt32(file);
len = ProtoReader.DirectReadLittleEndianInt32(file);
// assume GetObjectType returns typeof(TradeMessage) for our objType
Type type = GetObjectType(objType);
msg = RuntimeTypeModel.Default.Deserialize(file, null, type, len, null);
So apparently, i was doing a very silly mistake while creating the binary files. I did not open the file in binary mode when i wrote protobuf data to it causing it to add weird ascii characters in the middle. This caused an issue while reading the data using protobuf-net library. The issue is resolved here. Shouldn't have taken so long to resolve this.
I have a function in my program that outputs a data structure that consists of three doubles in two formats, one text and one binary.
When I run the program in debug and release modes, I end up with different binary outputs but identical text outputs. What is going on?
Here is the binary output code:
void outputPoints(xyz* points, string description, int length, param parameters)
{
stringstream index;
index.str("");
index << setw( 3 ) << setfill( '0' ) << parameters.stage;
string outputName = parameters.baseFileName + " " + index.str() + " " + description + ".bin"; // create file name
ofstream output; // create output object
cout << "Output " << outputName.c_str() << "...";
output.open(outputName.c_str(), std::ios::binary | std::ios::out); // open or create file for output
output.write(reinterpret_cast<char*>(points), (sizeof(xyz) * length));
output.close(); // close output object
cout << "done" << endl;
}
The debug build usually initializes variables with some patterns. Usually data allocated has the content CDCD, deleted objects are overwritten with FEEE. The CDCD pattern is overwritten when you initialize your variables. The release build doesn't initiliaze with these patterns.
It's worth to check your program for uninitialized variables. You can define a Dump function that just prints the (fist few bytes of) the suspected variables.
I don't know whether you got a solution for your issue and I did not look at your code.
I had the same issue because I was adding unsigned char and unsigned short and saving into unsigned short. I changed all variables to unsigned short and the issue was solved.