free(): invalid pointer when using scanf - c++

Hello guys so this is my code.
I could not use cin nor getline() so I had to use scanf.
It reads all the values in as expected but after entering the last value it says:
free(): invalid pointer ./comp: line 8: 877 Aborted (core dumped) ./$BIN
Anyways, here is the code.
Help would be appreciated.
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
// n -> amount of lines of code.
// q -> amount of queries.
int n, q;
cin >> n >> q;
// Handle source code Input.
vector<string> v(n);
for (unsigned i = 0; i < n; ++i)
{
cout << "i: " << i << endl;
scanf("%s", &v[i]);
}
return 0;
}

scanf is designed to work with character buffers, not strings. You probably want to use std::string (it's more intuitive and manages memory for you), so scanf is a poor fit. There's a version of getline that works with string.
std::vector<std::string> v(n);
for (int i = 0; i < n; i++) {
cout << "i: " << i << endl;
std::getline(std::cin, v[i]);
}

The %s specifier of scanf() expects a pointer to a char[] array, not a std::string object. By reading directly into a std::string object, you are corrupting its internals.
So, you need to either:
read into a char[] first, then assign that to your std::string:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
// n -> amount of lines of code.
// q -> amount of queries.
int n, q;
cin >> n >> q;
// Handle source code Input.
vector<string> v(n);
char buf[256];
for (unsigned i = 0; i < n; ++i)
{
cout << "i: " << i << endl;
scanf("%255s", buf);
v[i] = buf;
/* or:
int len = scanf("%255s", buf);
v[i] = string(buf, len);
*/
}
return 0;
}
pre-allocate the std::string's internal character buffer, then read directly into it (note, this approach is only guaranteed to work in C++11 and later, but in practice will typically work in most implementations of std::string in earlier versions, too):
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
// n -> amount of lines of code.
// q -> amount of queries.
int n, q;
cin >> n >> q;
// Handle source code Input.
vector<string> v(n);
for (unsigned i = 0; i < n; ++i)
{
cout << "i: " << i << endl;
v[i].resize(256);
int len = scanf("%255s", &v[i][0]/* or: v[i].data() in C++17 and later */);
v[i].resize(len);
}
return 0;
}

Related

Changing size value for an array c++

Making a program that reads integers from a file and creates an array, I have that part completed however I am trying to figure out how to change the SIZE value depending on how many ints are in the file. This file has 15 integers but another file may have more and this array will not take in all the ints.
using namespace std;
const int SIZE = 15;
int intArray[SIZE];
void readData(istream& inFile) {
for (int i = 0; i < SIZE; i++){
inFile >> intArray[i];
cout << intArray[i] << " ";
}
}
int main() {
ifstream inFile;
string inFileName = "intValues.txt";
inFile.open(inFileName.c_str());
int value, count = 0;
while(inFile >> value){
count += 1;
}
cout << count;
readData(inFile);
return 0;
}
As you can see I have a while loop counting the number of ints in the file however when I assign that to the size value I was running into many different issues.
A fixed-sized array simply cannot be resized, period. If you need an array whose size can change at runtime, use std::vector instead.
More importantly, you are reading through the entire file just to count the number of integers, and then you are trying to read the values from where the previous loop left off. You are not seeking the ifstream back to the beginning of the file so you can re-read what you have already read.
Try something more like this instead:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
int main() {
string inFileName = "intValues.txt";
ifstream inFile(inFileName.c_str());
int value, count = 0;
while (inFile >> value){
++count;
}
cout << count;
std::vector<int> intArray;
intArray.reserve(count);
inFile.seekg(0);
while (inFile >> value){
intArray.push_back(value);
cout << value << " ";
}
// use intArray as needed...
return 0;
}
Alternatively, don't even bother counting the integers, just let the std::vector grow as needed, eg:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
int main() {
string inFileName = "intValues.txt";
ifstream inFile(inFileName.c_str());
vector<int> intArray;
int value;
while (inFile >> value){
intArray.push_back(value);
cout << value << " ";
}
// use intArray as needed...
// you an get the count from intArray.size()
return 0;
}

Writing a C++ program to print the letters of a string in a chaotic order

What I'm trying to do is this:
User enters a string (For example: "Hello")
The program returns the same string, but in a random order(It can be "elHlo" or any other order possible)
So far I've written this code, but the problem is that sometimes the randomly generated numbers are the same, so it might print the same indexes(letters) twice or more times:
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;
int main(){
cout << "Say something: ";
string text;
getline(cin, text);
cout << "\nChaotic text: ";
srand(time(0));
for(unsigned int j=0; j<text.length(); j++){
int randomLetter = rand()%text.length();
cout << text.at(randomLetter);
}
return 0;
}
Can anyone help me fix it?
You can use std::shuffle (since C++11):
#include <iostream>
#include <string>
#include <random>
#include <algorithm>
using namespace std;
int main(){
cout << "Say something: ";
string text;
getline(cin, text);
cout << "\nChaotic text: ";
std::mt19937 g(time(0));
std::shuffle(text.begin(), text.end(), g);
cout << text;
return 0;
}
Or std::random_shuffle (if you are using old specification):
#include <iostream>
#include <string>
#include <cstdlib>
#include <algorithm>
using namespace std;
int main(){
cout << "Say something: ";
string text;
getline(cin, text);
cout << "\nChaotic text: ";
srand(time(0));
std::random_shuffle(text.begin(), text.end());
cout << text;
return 0;
}
Instead of calling rand() one time, which can generate an index you have called before, you can keep generating a new index while keeping tracking of all generated indices in a hashtable.
std::unordered_map<int, bool> done;
for (unsigned int j = 0; j < text.length(); j++) {
int randomLetter = rand() % text.length();
while (done[randomLetter] == true) // while it's been marked as finished, generate a new index.
randomLetter = rand() % text.length();
cout << text.at(randomLetter);
done[randomLetter] = true; // mark it as finished.
}
Alternatively, you can use std::random_shuffle instead, which should save you the hassle.
std::random_shuffle (text.begin(), text.end());
std::cout << text << '\n';

How to get the average from data.txt file with C++?

Our professor wants us to fix the code which counts the amount of values in a data.txt file and computes their average. Here is the code:
#include <cstdlib>
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
int main(int argc, char *argv[])
{
string s;
ifstream f;
int nItems;
double * data;
double sum=0;
vector < double > data2;
double item;
cout <<"File name: ";
cin >> s;
f.open (s.c_str() );
while (! f.eof() )
{
f >> item;
data2.push_back(item);
}
for (int i =0; i < nItems; i++)
{
sum += data[i];
}
cout << "The average is " << sum/nItems <<".\n";
cout << "Press the enter key to continue ...";
cin.get();
return EXIT_SUCCESS;
}
His instructions were:
Modify code worked on today so that the average of data in vector < double > data is computed properly. Right now the code just gives you a value which isn't the average.
I tried changing the nItems variable into 12 and that seemed to work, but the goal of the code is to determine nItems and use that to find the average, which I can't seem to figure out.
You use data for which you haven't allocated any memory when you summarise That causes undefined behaviour. You've stored your values in data2. Remove variables you don't need. Also, using namespace std is considered bad practice.
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <numeric> // std::accumulate
int main(int, char**) {
std::string filename;
std::cout << "File name: ";
std::cin >> filename;
std::ifstream f(filename); // no need for .c_str()
std::vector<double> data;
double item;
// instead of checking for eof, check if extraction succeeds:
while(f >> item) {
data.push_back(item);
}
// a standard way to sum all entries in a container:
double sum = std::accumulate(data.begin(), data.end(), 0.);
std::cout << "The sum is " << sum << "\n";
// use the containers size() function. it returns the number of items:
std::cout << "The average is " << (sum / data.size()) << "\n";
}
Hey looks like you weren't reading the numbers in from the txt file.
Here I look through the input file once just to count how many numbers there are
so I can make the array.
Then I look through it again to fill the array.
#include <cstdlib>
#include <iostream>
#include <fstream>
// f here stands for find, fstream gives you files
using namespace std;
int main(int argc, char *argv[]) {
string s;
ifstream f;
// input file stream
int nItems;
double * data;
double sum=0;
cout << "File name: ";
cin >> s;
f.open (s.c_str() );
// s.c_str will return a char array equivalent of the string s
nItems=0;
int input =0;
while (f >> input) {//first loop reading through file to count number of items
nItems++;
}
f.close();
data = new double[nItems]; //Make the array
f.open (s.c_str() );//open file for second read
int i=0;
while (f >> input) {//Second loop through file fills array
data[i] = input;
i++;
}
f.close();
for (int i = 0; i < nItems; i++) {
sum += data[i];
}
cout << "The average is " << sum / nItems << ".\n";
cout << endl;
system("pause");
return 0;
}

C++ simple string program

beginner here
i wrote the below in C++, it's a short program that currently takes 2 words as inputs, and outputs the same words back but the words are split into even and odd instead. I would like to be able to do this for 'T' words instead, but I can't figure it out. I would like to be able to first input the number of words that will follow, for example 10. Then to input the words and get T results back. So instead of just 2 words, an unlimited amount with the user specifying.
I need to put the below into a function and go from there sometime, but I want to learn the best technique to do so - any advice please?
Thanks!
Alex
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main() {
int T;
cin >> T;
string FirstWord;
cin >> FirstWord;
int LengthFirst;
LengthFirst = FirstWord.length();
string EvenFirst;
string OddFirst;
for (int i = 0; i < LengthFirst; i += 2){
EvenFirst = EvenFirst + FirstWord[i];
}
for (int i = 1; i < LengthFirst; i += 2){
OddFirst = OddFirst + FirstWord[i];
}
string SecondWord;
cin >> SecondWord;
int LengthSecond;
LengthSecond = SecondWord.length();
string EvenSecond;
string OddSecond;
for (int i = 0; i < LengthSecond; i += 2){
EvenSecond += SecondWord[i];
}
for (int i = 1; i < LengthSecond; i += 2){
OddSecond += SecondWord[i];
}
cout << EvenFirst << " " << OddFirst << endl;
cout << EvenSecond << " " << OddSecond << endl;
return 0;
}
Think I got it here, I was over-thinking this one
I put it in a for loop, as below - so any number of words can be input, user has to input the number of test cases at the
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main() {
int T;
cin >> T;
for (int i = 0; i < T; i++){
string FirstWord;
cin >> FirstWord;
int LengthFirst;
LengthFirst = FirstWord.length();
string EvenFirst;
string OddFirst;
for (int i = 0; i < LengthFirst; i += 2){
EvenFirst = EvenFirst + FirstWord[i];
}
for (int i = 1; i < LengthFirst; i += 2){
OddFirst = OddFirst + FirstWord[i];
}
cout << EvenFirst << " " << OddFirst << endl;
}
return 0;
}
Ultimately, you are performing the same task N times.
First, let's discuss how to store the information. Functionally, we have one string as input which yields two strings as output. std::pair (from <utility>) lets us easily represent this. But for sake of even-odd, std::array might be a better representation for us. Since we have a variable number of words as input, a variable number of std::array will be output. std::vector (from <vector>) is our friend here.
Second, let's discuss how to process the information. Using named variables for each output component does not scale, so let's switch to a fixed array (noted below as array<string,2>. By switching to a fixed array for output, addressing each split becomes a function of the loop index (index % 2). Below is a solution that generalizes on a known split size at compile time.
#include <string>
#include <array>
#include <vector>
#include <iostream>
int main() {
int N;
std::cin >> N;
constexpr const int Split = 2;
using StringPack = std::array<std::string, Split>;
std::vector<StringPack> output;
for (int wordIndex = 0; wordIndex < N; ++wordIndex) {
std::string word;
std::cin >> word;
StringPack out;
{
int index = 0;
for (char c : word) {
out[index % Split] += c;
++index;
}
}
output.emplace_back(out);
}
for (const auto & out : output) {
for (const auto & word : out) {
std::cout << word << ' ';
}
std::cout << '\n';
}
}

array size and split of string

Ok guy i had to make a program to split elements of a string. And after that print those words.
there are some problems i am facing:
1) the array prints more than the size of the words in string i want that it should end printing as soon as last word is printed. i tried to prevent that but it always gives runtime error when i try to break at the last word.
2)is there any other efficient way to split and print ???
#include <sstream>
#include <iostream>
#include<cstdio>
#include<cstdlib>
#include <string>
using namespace std;
int main()
{
std::string line;
std::getline(cin, line);
string arr[1000];
int i = 0;
int l=line.length();
stringstream ssin(line);
while (ssin.good() && i < l)
{
ssin >> arr[i];
++i;
}
int size = sizeof(arr) / sizeof(arr[0]);
for(i = 0; i <size; i++){
cout << arr[i] << endl;
}
return 0;
}
int size = sizeof(arr) / sizeof(arr[0]);
That is a compile time value, and it's always going to be the number of elements in your array (1000). It has no idea how many strings you assigned to in your loop. You stored the number of successfully read strings (plus 1) in the i variable, so you could do this instead:
int size = i - 1;
But if it were up to me, I would just use a growable structure, like vector (#include <vector>)
std::vector<std::string> arr;
std::string temp;
while (ssin >> temp)
{
arr.push_back(temp);
}
for (auto const & str : arr)
{
std::cout << str << std::endl;
}
/* If you're stuck in the past (can't use C++11)
for (std::vector<std::string>::iterator = arr.begin(); i != arr.end(); ++i)
{
std::cout << *i << std::endl;
}
*/
For general purpose character based splitting, I would much prefer boost::split (I know you can't use it, but for future reference)
std::vector<std::string> arr;
boost::split(arr, line, boost::is_any_of(".,;!? "));
Read up on the function strtok. It is old school but very easy to use.
1) there are a couple of changes you should make to your program:
#include <sstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
std::string line("hello string world\n");
string arr[1000];
int i = 0;
stringstream ssin(line);
while (ssin.good() && i < 1000)
{
ssin >> arr[i++];
}
int size = i-1;
for(i = 0; i < size; i++){
cout << i << ": " << arr[i] << endl;
}
return 0;
}
namely, you don't want to print sizeof(arr)/sizeof(arr[0]) (i.e. 1000) elements. There is no point in the condition i < l
2) stringstream is fine if you just want to separate the single strings; if more is needed, use boost/tokenizer for splitting strings. It's modern c++, once you try it you'll never come back!
this is the best method i think no worry now
#include <sstream>
#include <iostream>
#include<cstdio>
#include<cstdlib>
#include <cstring>
#include <string>
using namespace std;
int main ()
{
std::string str;
std::getline(cin, str);
string arr[100];
int l=0,i;
char * cstr = new char [str.length()+1];
std::strcpy (cstr, str.c_str());
// cstr now contains a c-string copy of str
char * p = std::strtok (cstr,".,;!? ");
while (p!=0)
{
//std::cout << p << '\n';
arr[l++]=p;
p = strtok(NULL,".,;!? ");
}
for(i = 0; i <l; i++)
{
cout << arr[i] << endl;
}
delete[] cstr;
return 0;
}