This question already has answers here:
How do you 'realloc' in C++?
(4 answers)
Closed 9 months ago.
I'm trying to create a program that stores words of a string within the space in an array(For example: If user inputs - "Hello what's up" ,So i want to store Hello, What's,Up in an array of thier respective indices (Hello in 0th index,What's in 1st index and up in 2nd index). I'm using c method of DMA in c++ to achieve this.
Following is my code-
https://code.sololearn.com/cNWxZV9IoG4q/?ref=app
#include <iostream>
#include <sstream>
#include <cstdlib>
using namespace std;
int main() {
string sentence;
getline(cin,sentence);
stringstream ss(sentence);
string *words;
int count=0;
while(ss>>sentence)
{
if(count==0)
{
words=
(string*)malloc((count+1)*sizeof(string));
*(words+count)=ss.str();
count++;
continue;
}
words=(string*)realloc(words, (count+1)*sizeof(string));
*(words+count)=ss.str();
free(words);
count++;
}
return 0;
}
But , I'm getting error , Could anyone please fix it?
Don't use C in C++. Just use a std::vector to store the words:
std::string word;
std::vector<std::string> words;
while (ss >> word) {
words.push_back(word);
}
And then you can print the individual words like so:
for (auto& word: words) {
std::cout << word << '\n';
}
Or if you wish to use indices:
for (std::size_t i = 0; i < words.size(); ++i) {
std::cout << i << ": " << words[i] << '\n';
}
The reason why your code fails is, as #heapunderrun mentioned, the fact that std::string has a constructor. If you don't call the constructor in some way, then the string will be in an indeterminate state. When you try to assign to such a string, like in:
*(words+count)=ss.str();
Then your program will crash. If you really want to use manual memory allocation, then you have to use new and delete. You can use malloc() if you really want to, but then you still should use placement new to ensure the std::string objects are correctly constructed inside the memory you allocated. Finally, you probably can't use realloc() safely, you would have to malloc() a new array, copy everything properly to the new array, then free() the old array.
Related
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
char a[n+1]; // intializing array
cin.getline(a,n); // inputting array
cin.ignore();
int maxlen=0,curr=0,i=0;
while(1)
{
if (a[i] ==' ' || a[i] == '\0'){
maxlen=max(curr,maxlen);
curr=0;
}
curr++;
if (a[i]=='\0'){
break;
}
i++;
}
cout<<maxlen;
}
here i am trying to find the max length of word in this sentence but i am not able to save the sentence or input the array.
To check i put cout for array and its not printing the array i inputed i want to know the reason
error C2131: expression did not evaluate to a constant (6):
This is caused due to using non-standard C++ here:
cin>>n;
char a[n+1]; // intializing array
Arrays in C++ must be declared using a constant expression, not a runtime-based expression. Since n is only known at runtime, this is not legal C++.
As to solving the issue, you don't need raw char arrays. This can easily be done using std::string. In addition, using std::stringstream will make the code even simpler by not having to check for whitespace:
#include <algorithm>
#include <string>
#include <iostream>
#include <sstream>
int main()
{
std::string sentence;
// Read the sentence
std::getline(std::cin, sentence);
// Parse each word
std::stringstream strm(sentence);
std::string word;
size_t maxLen = 0;
while (strm >> word)
maxLen = std::max(maxLen, word.size());
// Output results
std::cout << sentence << "\n" << maxLen;
}
For this input:
This is a test of getting the longest word in a string
the output is:
This is a test of getting the longest word in a string
7
Finally, you should follow a good C++ book instead of going to websites that shows any coding using:
#include<bits/stdc++.h>
or the invalid array syntax mentioned above.
No reputable C++ book, or reputable C++ website that has been peer-reviewed will show code using that header, or the invalid array syntax.
If you go to a website that shows code like this, and the website's purpose is to teach C++, it isn't one you should learn any C++ from.
I believe my error is within my writeline function, when I attempt to write the contents of the vector to the new file using a while loop.
//Read from txt file, write to new text file
#include<iostream>
#include<fstream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
void readline();
void sortline(vector<string>& sortthis);
void writeline(vector<string>& list);
int main()
{
readline();
system("pause");
return 0;
};
void readline()
{
string line;
vector<string> lines;
ifstream myfile("classes.txt");
if (myfile.is_open())
{
while (myfile.good())
{
getline(myfile, line);
lines.push_back(line);
};
myfile.close();
}
cout << "readline() has run" << endl;
sortline(lines);
writeline(lines);
};
void sortline(vector<string>& sortthis)
{
sort(sortthis.begin(), sortthis.end());
};
void writeline(vector<string>& list)
{
ofstream myfile2("new.txt");
if (myfile2.is_open())
{
int i = 0;
while(i !=list.size()-1)
{
myfile2 << list[i] << endl;
i++;
};
myfile2.close();
};
cout << "writeline() has run" << endl;
};
this is a project from a semester ago that i'm revisiting. I wrote the program on my mac, now i'm trying to run it on my windows comp with visual studio. I'll describe what I'm attempting to do, I apologize if my choice of words is terrible in advance. anywhere I put a * is where I'm not sure what is happening, but I'll take a stab at it.. any explanations of my code is very appreciated!!
my readline() function does the following: creates a string called line, creates a vector of string type called lines, **input the file classes.txt and establish myfile as it's object, then open myfile for writing, **use the while loop to write the lines from the txt into the myfile object, then close myfile, print out a statement to let the user know readline() has run, then **pass the vector called lines into the sortline function, and then pass lines into the writeline function.
** sortline takes in a vector of strings as its arg, and assigns it the object sortthis?? then I'm not sure what happens, but it looks like i applied a sorting algorithm, anybody have any thoughts?
and finally we get to my writeline function which takes in a vector of strings as its arg and assigns them the name lines (is that correct?) i then want to establish a new out file stream to a new textfile called "new.txt" with an object name myfile2, if myfile2 is open, then i want to write all the lines from the vector of strings(which contain the contents of the original text file) into myfile2, which will write them to the new.txt file, then close myfile2, print a message stating the function has run, and that is all.
The way you loop through list in writeline is not safe. You should use a for loop or a while loop with iterator. As it is, your code probably doesn't do what you intend it to do even if there are several elements in list. Consider the following:
std::vector<std::string> vLines;
vLines.push_back("Hello");
vLines.push_back("File");
vLines.push_back("World");
std::ofstream of("file.txt");
int i = 0;
while (i != vLines.size() - 1)
{
of << vLines[i] << std::endl;
++i;
}
Even with several elements in vLines, this will only actually print output 2 elements into of.
i will be 0 which is not 2, so "Hello" will be output to of.
i will be 1 which is not 2, so "File" will be output to of.
i is now 2, which is equal to 2, so "World" will not be output to of.
That's with elements. If there are 0 elements in vLines, you will be indexing out of bounds (which I suspect is what you are doing, hence your error):
std::vector<std::string> vLines;
std::ofstream of("file.txt");
int i = 0;
while (i != vLines.size() - 1)
{
of << vLines[i] << std::endl;
++i;
}
i will be 0, which is not equal to -1, so the code will run and try to output vLines[0] to of, but there is no vLines[0]! I suspect this is what you are experiencing.
This will go away if you use a proper range-based loop instead (credit to #WhozCraig for C++11 solution):
for (auto const& s : vLines)
of << s;
Or if you don't have C++11 you can still mimic a proper range-based loop with the following:
for (int i = 0; i < vLines.size(); ++i)
of << vLines[i] << std::endl;
Or an iterator:
for (auto it = vLines.begin(); it != vLines.end(); ++it)
of << *it << std::endl;
You will now output all elements in your std::vector to your std::ofstream as well as properly handle situations where there are no elements.
Please help me to figure out why there is a question mark at my string output. I have been working on this simple reverse a string practice. My code can do it correctly. Then I try to store the reversed string into an array and then convert this array to a string. So here is something wired happened. There is always a question mark at the end of that string. Please teach me the reason of it, and how to get rid of this question mark. Here is my code. Thank you so much
#include <string>
using namespace std;
int main()
{
cout<<"Please enter a string."<<endl;
string str;
cin >> str;
int i=0;
int length = str.length();
char arr[length];
//cout<<length;
while (length != 0) {
arr[i] = str.at(length-1);
length--;
cout<<arr[i];
++i;
}
cout<<endl;
string stri(arr);
cout<<endl<<stri<<endl;
cout<<stri[4];
return 0;
}
A string in C (or many other languages) needs to be terminated by a '\0'. After all, you don't know how large the memory your char* points to is. So you need char[length + 1]. Also, variable-length arrays aren't part of C++. You need to use new[]/delete[] or malloc()/free():
char * arr = new char[length + 1]; // enough space for string + '\0'
char[length] = '\0'; // terminate the string with '\0'
while (length != 0) {
// ... // reverse
}
cout << endl;
string stri(arr); // create the new string
delete[] arr; // don't forget to deallocate the memory
However, if you're dropping down to manual memory allocation, you're usually missing something from the standard library. And indeed, you could simply use the right constructor (it's (4), simplified below):
template <class InputIt>
string::string(InputIt first, InputIt last);
And luckily, std::string provides input iterators that traverse the string backwards via std::string::rbegin() and std::string::rend(). Now your code gets a lot easier:
#include <iostream>
#include <string>
int main()
{
std::cout << "Please enter a string." << std::endl;
std::string str;
std::cin >> str;
std::cout << std::endl;
// Create the new reversed string directly:
std::string reversed_string(str.rbegin(), str.rend());
std::cout << reversed_string << std::endl;
return 0;
}
char arr[length];
should be
char arr[length + 1];
EDIT: or rather (as Jonathan Potter points out, since length is not a compile time constant, your code likely only compiles because this is permitted by your specific compiler, e.g. GNU C++):
char *arr = new char[length + 1];
(and delete [] arr; at some point)
to store the terminating '\0':
arr[length] = '\0';
Can someone explain to me how to properly search for a "tab" character stored in a string class?
For example:
text.txt contents:
std::cout << "Hello"; // contains one tab space
User enters on prompt: ./a.out < text.txt
main.cpp:
string arrey;
getline(cin, arrey);
int i = 0;
while( i != 10){
if(arrey[i] == "\t") // error here
{
std::cout << "I found a tab!!!!"
}
i++;
}
Since there is only one tab space in the textfile, I am assuming it is stored in index [0], but the problem is that I can't seem to make a comparison and I don't know any other way of searching it. Can someone help explain an alternative?
Error: ISO C++ forbids comparison between pointer and integer
First of all, what is i? And secondly, when you use array-indexing of a std::string object, you get a character (i.e. a char) and not a string.
The char is converted to an int and then the compiler tries to compare that int with the pointer to the string literal, and you can't compare plain integers with pointers.
You can however compare a character with another character, like in
arrey[i] == '\t'
std::string::find() might help.
Try this:
...
if(arrey.find('\t') != string::npos)
{
std::cout << "I found a tab!!!!";
}
More info on std::string::find is available here.
Why not using what C++ library provides? You could do it like this:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string arrey;
getline(cin, arrey);
if (arrey.find("\t") != std::string::npos) {
std::cout << "found a tab!" << '\n';
}
return 0;
}
The code is based on this answer. Here is the ref for std::find.
About your edit, how are sure that the input is going to be 10 positions? That might be too little or too big! If it is less than the actual size of the input, you won't look all the characters of the string and if it is too big, you are going to overflow!
You could use .size(), which says the size of the string and use a for loop like this:
#include <iostream>
#include <string>
using namespace std;
int main() {
string arrey;
getline(cin, arrey);
for(unsigned int i = 0; i < arrey.size(); ++i) {
if (arrey[i] == '\t') {
std::cout << "I found a tab!!!!";
}
}
return 0;
}
I have a large file (50x11k) of a grid of numbers. All i am trying to do is place the values into a vector so that i can access the values of different lines at the same time. I get a seg fault everytime (i cannot even do a cout before a the while loop). Anyone see the issue?
If there is an easier way to do this then please let me know. Its a large file and I need to be able to compare the values of one row with another so a simple getline does not work, Is there a way to jump around a file and not "grab" the lines, but just "examine" the lines so that I can later go back an examine that same line by putting in that number? Like looking at the file like a big array? I wanna look at the third line and 5 character in that line at the same time i look at the 56th line and 9th character, something like that.
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
//int g_Max = 0;
int main() {
vector<vector<string> > grid;
ifstream in("grid.txt");
int row = 0;
int column = 0;
string c;
if (!in) {
cout << "NO!";
}
while (!in.eof()) {
c = in.get();
if ( c.compare("\n") == 0) {
row++;
column = 0;
}
else {
c = grid[column][row];
cout << grid[column][row];
column++;
}
}
return 0;
}
vector<vector<string> > grid;
This declares an empty vector, with no elements.
c = grid[column][row];
This accesses elements of the vector, but there are no elements.
If you change it to use vector::at() instead of vector::operator[] like so:
c = grid.at(column).at(row);
then you'll get exceptions telling you you're accessing out of range.
You need to populate the vector with elements before you can access them. One way is to declare it with the right number of elements up front:
vector<vector<string> > grid(11000, std::vector<string>(50));
You probably also want to fix your IO loop, testing !in.eof() is usually wrong. Why not read a line at a time and split the line up, instead of reading single characters?
while (getline(in, c))
If all you need is to access all lines at once why you don't declare it as std::vector<std::string> and each line is an string??
std::string s;
std::vector<std::string> lines;
while( std::getline(in, s) ) lines.push_back( s );
std::cout << "File contain " << lines.size() << " line" << std::endl;
std::cout << "Char at [1][2] is " << lines[1][2] << std::endl; // assume [1][2] is valid!