Can't write string on file C++ - c++

I'm trying to emulate a shift register of 32 bits. But I can't even write, neither the input or output on the file. It simply runs the file and closes. There is nothing written in there. Tried some solutions here, but nothing worked so far. The input is a string of 32 bits like this
"00000000000000000000000000000011".
The output should look like this
"00000000000000000000000000001100".
Shifting two bits to the left. I haven't finished the shift yet, I'm trying to understand why it doesn't show anything.
The weird thing about this is, I've created 32 bits multiplexes the same way and it works fine.
void deslocador::shift(std::vector<std::string> entrada)
{
std::ofstream shifter("shift_left2.tv", std::ofstream::out);
std::vector<std::string> saida;
if(shifter.is_open())
{
for(unsigned int i = 0; i < 3; i++)
{
saida[i] = entrada[i];
saida[i].erase(saida[i].begin());
saida[i].erase(saida[i].begin());
saida[i] += "00";
shifter << entrada[i] << "_" << saida[i] << std::endl;
}
}else
{
std::cout << "Couldn't open file!";
}
shifter.close();
}

std::vector<std::string> saida;
This instantiates a new vector. Like all new vectors, it is completely empty, and contains no values.
for(unsigned int i = 0; i < 3; i++)
{
saida[i] = entrada[i];
This assigns four values to saida[0] through saida[3]. Unfortunately, as we've just discovered, the saida vector is completely empty and contains nothing. This attempts to assign new values to nonexistent values in the vector, so this is undefined behavior, and pretty much a guaranteed crash.
Additionally, no attempt is made to verify whether the entrada vector contains at least four values, this would be yet another reason for undefined behavior, and a crash.
It is unclear what the intent of the shown code is, so it's not possible to offer any suggestion of possible ways to fix it. The description of the code does not match its contents. It is unclear what relationship exists between "32 bits" and a vector of strings, that may or may not have four values in it.
The only thing that can be determined is that you get no output because your program crashes because of undefined behavior. Before you can assign a value to the ith element in the vector, the ith element must already exist. It doesn't, in the shown code. This results in undefined behavior and a crash.
There are various ways of placing new values in a vector. A vector can be resize()d, or new values can be push_back()ed into a vector. It is unclear what should be done in this case, so for additional information and examples, see your C++ book so you can learn more about how either approach (and other approaches) work, so you can decide how you want to do what you are trying to do.

Here is what I did to work!
void deslocador::shift(std::vector<std::string> entrada)
{
std::ofstream shifter("shift_left2.tv", std::ofstream::out);
std::vector<std::string> saida;
saida.resize(entrada.size());
if(shifter.is_open())
{
for(unsigned int i = 0; i < entrada.size(); i++)
{
saida[i] = entrada[i];
saida[i].erase(saida[i].begin());
saida[i].erase(saida[i].begin());
saida[i] += "00";
shifter << entrada[i] << "_" << saida[i] << std::endl;
}
}else
{
std::cout << "Couldn't open file!";
}
shifter.close();
}

Related

Why does my function not switch the first character with the last one of my string?

I picked up a challenge on r/dailyprogrammer on reddit which wants me to match a necklace and put the last letter at the beginning of a string. I've considered using nested for loops for this but this has made me really confused.
Instead I chose the way of replacing the last with the first character in an if-statement. But I am not getting my desired output with it, though I've tried everything what comes into my mind.
I used even std::swap() which didn't lead me to success either.
Here's the code:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
string same_necklace(string& sInput, string& sOutput)
{
for (string::size_type i = 0; i < sInput.size(); i++)
{
if (sInput[i] == sInput.size())
{
sInput[0] = sInput[sInput.size()];
}
}
for (string::size_type j = 0; j < sOutput.size(); j++)
{
if (sOutput[j] == sOutput.size() - 1)
{
sOutput[0] = sOutput[sOutput.size()];
}
}
return sInput, sOutput;
}
int main()
{
system("color 2");
string sName{ "" };
string sExpectedOutput{ "" };
cout << "Enter a name: ";
cin >> sName;
cout << "Enter expected output: ";
cin >> sExpectedOutput;
cout << "Result: " << same_necklace(sName , sExpectedOutput) << endl;
return 0;
}
And of course the link to my challenge (don't worry, it's just Reddit!):
https://www.reddit.com/r/dailyprogrammer/comments/ffxabb/20200309_challenge_383_easy_necklace_matching/
While I am waiting (hopefully) for a nice response, I will keep on trying to solve my problem.
In your if you compare the value of the current index (inside the loop) with the size of the string. Those are two unrelated things.
Also, you use a loop though you only want to do something on a single, previously known index.
for (string::size_type i = 0; i < sInput.size(); i++)
{
if (sInput[i] == sInput.size())
{
sInput[0] = sInput[sInput.size()];
}
}
You could change the if condition like this to achieve your goal:
if (i == sInput.size()-1) /* size as the index is one too high to be legal */
But what is sufficient and more elegant is to drop the if and the loop. completely
/* no loop for (string::size_type i = 0; i < sInput.size(); i++)
{ */
/* no if (sInput[i] == sInput.size())
{*/
sInput[0] = sInput[sInput.size()-1]; /* fix the index*/
/* }
} */
I.e.
sInput[0] = sInput[sInput.size()-1]; /* fix the index*/
Same for he output, though you got the correct index already correct there.
This is not intended to solve the challenge which you linked externally,
if you want that you need to describe the challenge completely and directly here.
I.e. this only fixes your code, according to the desription you provide here in the body of your question,
"put the last letter at the beginning of a string".
It does not "switch" or swap first and last. If you want that please find the code you recently wrote (surely, during your quest for learning programming) which swaps the value of two variables. Adapt that code to the two indexes (first and last, 0 and size-1) and it will do the swapping.
So much for the loops and ifs, but there is more wrong in your code.
This
return sInput, sOutput;
does not do what you expect. Read up on the , operator, the comma-operator.
Its result is the second of the two expressions, while the first one is only valuated for side effects.
This means that this
cout << "Result: " << same_necklace(sName , sExpectedOutput) << endl;
will only output the modified sExpectedOutput.
If you want to output both, the modified input and the modified output, then you can simply
cout << "Result: " << sName << " " << sExpectedOutput << endl;
because both have been given as reference to the function and hence both contain the changes the function made.
This also might not answer the challenge, but it explains your misunderstandings and you will be able to adapt to the challenge now.
You have not understand the problem i guess.
Here you need to compare two strings that can be made from neckless characters.
Lets say you have neckless four latters word is nose.
Combination is possible
1)nose
2)osen
3)seno
4)enos
your function (same_necklace) should be able to tell that these strings are belongs to same necklace
if you give any two strings as inputs to your function same_necklace
your function should return true.
if you give one input string from above group and second input string from other random word thats not belongs to above group, your function should return false.
In that sense, you just take your first string as neckless string and compare other string with all possible combination of first string.
just move move you first latter of first input string to end and then compare each resulting string to second input string.
below is the function which you can use
void swap_character(string &test)
{
int length = test.length();
test.insert(length, 1, test[0]);
test.erase(0, 1);
}

Issue Read/Write array of structure in binary file in c++

I want to write my array structure in to a binary file.
My structure
typedef struct student{
char name[15];
vector<int> grade;
}arr_stu;
I can write and read back my data if I write and read in the same program; but if I create another program for read data only and put the binary file, it does not work because the vector grade is null.
size = 0;
unable to read from memory
Program to write array structure to file
int main()
{
arr_stu stu[100];
for (size_t i = 0; i < 100; i++)
{
strcpy(stu[i].name, randomName());
for (size_t j = 0; j < 10; j++)
{
stu[i].grade.push_back(randomGrade());
}
}
ofstream outbal("class", ios::out | ios::binary);
if (!outbal) {
cout << "Cannot open file.\n";
return 1;
}
outbal.write((char *)&stu, sizeof(stu));
outbal.close();
}
Program to read array structure to file
int main(){
feature_struc stu[100];
ifstream inbal("class", ios::in | ios::binary);
if (!inbal) {
cout << "Cannot open file.\n";
return 1;
}
inbal.read((char *)&stu, sizeof(stu));
for (size_t idx = 0; idx < 100; idx++)
{
cout << "Name : " << stu[idx].name << endl;
for (size_t index = 0; index < 10; index++)
{
cout << endl << "test: " << stu[idx].grade[index] << endl;
}
}
inbal.close();
return 0;
}
For me it seems like the use of vector pose the problem,
The reason that if we combine the two in one program it work well I think because vector is saved in the memory so it can still accessible.
Any suggestions?
You cannot serialize a vector like that. The write and read functions access the memory at the given address directly. Since vector is a complex class type only parts of its data content are stored sequentially at its base address. Other parts (heap allocated memory etc) are located elsewhere. The simplest solution would be to write the length of the vector to the file followed by each of the values. You have to loop over the vector elements to accomplish that.
outbal.write((char *)&stu, sizeof(stu));
The sizeof is a compile-time constant. In other words, it never changes. If the vector contained 1, 10, 1000, or 1,000,000 items, you're writing the same number of bytes to the file. So this way of writing to the file is totally wrong.
The struct that you're writing is non-POD due to the vector being a non-POD type. This means you can't just treat it as a set of bytes that you can copy from or to. If you want further proof, open the file you created in any editor. Can you see the data from the vector in that file? What you will see is more than likely, gibberish.
To write the data to the file, you have to properly serialize the data, meaning you have to write the data to a file, not the struct itself. You write the data in a way so that when you read the data back, you can recreate the struct. Ultimately, this means you have to
Write the name to the file, and possibly the number of bytes the name consists of.
Write the number of items in the vector
Write each vector item to the file.
If not this, then some way where you can distinctly figure out the name and the vector's data from the file so that your code to read the data parses the file correctly and recreates the struct.
What is the format of the binary file? Basically, you have to
define the format, and then convert each element to and from
that format. You can never just dump the bits of an internal
representation to disk and expect to be able to read it back.
(The fact that you need a reinterpret_cast to call
ostream::write on your object should tell you something.)

Accessing data inside an array via pointer error

I have 2 files in msg format. msg format is not important here.
car.msg
int speed;
int width;
cararr.msg
car mycar[];
I want to print all the information about all the cars that are present but I have no clue about the number of cars present(how big is the array) so I use the following technique to print the information.
so I do this:
cararr* ptr2car;
for(int i=0;mycar[i] != '\0'; i++){
cout << ptr2car->mycar[i].speed <<endl;
cout << ptr2car->mycar[i].width <<endl;
}
Despite this, I am receiving errors. I do not know what did I do wrong. I have no clue what approach should I use to get this output. please Help
Also why should I take a pointer to cararr, when I can just take an instance of cararr inst2car and do something like this:
cararr inst2car;
for(int i=0;mycar[i] != '\0'; i++){
cout << inst2car.mycar[i].speed <<endl;
cout << inst2car.mycar[i].width <<endl;
}
thanks
In general you need to know exactly what's at the end of the array. You need some sort of sentinel value to use as a delimiter to indicate the end of the array.
'\0' used in c strings is an example of such delimiter.
You need to ensure the last element in the array is such delimiter and check for it in the condition.
It's hard to give you more specific answer with such generic question.
For example, if you knew the last element will have speed -1, you can use that:
for(int i=0;mycar[i].speed != -1; i++) {

Array of Strings to Output File

I am writing a C++ code in which I have dynamically created an array of strings. I have written functions to output both the number of items in the string array as well as the array itself. The next thing I wanted to do is stored the elements of the array in a text file, but when I open the file I have written to, only the last element of the array shows up. Here is a sample of what I am doing:
int num_elem = ReadNumElem(); // my function that gets the number of elements in the array of strings
string *MyStringArray = ReadNames(num_elem); // my function that reads a file and outputs the necessary strings into the array
for(int i = 0; i < num_elem < ++i) {
ofstream ofs("C:\\Test\\MyStrings.txt")
ofs << MyStringArray[i] << endl; // I also tried replacing endl with a "\n"
}
I am new to C++, so I apologize if this is too simple, but I have been searching for some time now, and I can't seem to find a solution. The first two functions are not relevant, I only need to know how to output the data into a text file so that all the data shows up, not just the final element in the array. Thanks!
You are opening the file every time in the array and overwriting its contents.
Try:
ofstream ofs("C:\\Test\\MyStrings.txt");
for(int i = 0; i < num_elem ; ++i) {
ofs << MyStringArray[i] << endl; // I also tried replacing endl with a "\n"
}
ofs.close();
You need to declare the file outside of the loop
edit
Sorry I didn't mean to answer in one line but it has been done now anyway.

Newbie question on C++ array

I'm working through a demo program written by someone else, and I'm very confused about some of the statements they are using. I'm not very familiar with C++ (moreso with Obj-C) and I'm not sure if this is valid code or not. Take, for example, the following: (comments are mine)
int main(int argv, char** argc)
{
int perm [20]; //OK, so declare an array of ints, size = 20
for (int i=0; i < 20; i++)
perm = i; //whaaaaa??? thought you need to specify an element to assign to an array...
}
That is one example - my compiler throws an "incompatible types in assignment of 'int' to 'int [20]' error, but apparently others have been able to compile the program. Am I nuts, or is this bad code?
Here's another piece I just don't get:
int d[20] = {0}; //OK, another int array of size 20, initialized to 0's
for (int i = 1; i < n; i++)
{
d = d[i - 1]; //this I don't get - assign the array to one of its own elements??
if (invperm[i - 1] < b)
d++; //this would just increment to the next element?
}
I suspect the error is one of comprehension on my part, as if the code was bad other people would've commented on that fact...if anyone has a good explanation and/or resource I can read to understand this, I would be most appreciative!
Thanks!
*EDITED TO ADD*
In response to the answers below, I did copy/paste that code, and it looks intact to me...I can only assume when the original author posted it, it mangled it somehow. Thanks for the replies, I'm glad I had the right understanding, and I'll try and contact the author to see if there is an un-mangled copy out there somewhere!
All those examples are absolutely wrong. It looks like you lost [i] when you copied the code from wherever you got it from.
I have seen something similar with code sent over messenger programs that treat certain bits of text as emotes and replace them with images that don't get copied as text, but instead get dropped.
Your understanding is fine, that code is just entirely nonsensical.
d++; //this would just increment to the next element?
It would if d were a pointer. However since d is an array, it's simply illegal.
This is most certainly a copy/paste error.
I have succumbed to the temptation of copy/pasting code at one point during a game tech project involving Lua scripts. If the Lua script fails there is no feedback/output that indicates something is failed (which is very frustrating). After debugging for hours I realised my script was using 'smart quotes'.
Whilst this code is broken it can still teach you some things about C++.
int perm [20];
cout << endl << perm << endl;
cout << endl << &perm[0] << endl;
'perm' returns the memory address of the first element of the array. so when you are trying to assign 'i' to 'perm' in that main for loop (20 times) you will know now that you were trying to assign an integer to a memory address, hence the incompatible type error.
The second section however is verry broken and I can't discern much learning from this :P.
I added in an example program to show how pointers/arrays can be used:
#include <iostream>
using namespace std;
int main()
{
int d[20] = {0}; // 20 ints, set to 0
int * ptr = d; // points to d[0]'s memory address
for(int i = 0; i < 20; i++)
{
d[i] = 0 + i; // set array values
}
for(int i = 0; i < 20; i++)
{
// iterates through d and prints each int
cout << endl << "d[i]: " << d[i] << endl;
// dereferences the ptr to get the same int
// then incraments the position of the pointer for next time
cout << endl << "*ptr++: " << *ptr++ << endl;
}
getchar();
return(0);
}