C++ error: munmap_chunk(): invalid pointer - c++

My issue I assume is with &line.at(0). I had an error with it before, but dereferencing it took away the error. I am not sure why that is, as I was under the impression that my getline function would return the first line (one integer value that is the size of an array to sort), and the next would be a string of integers, separated by a space, that you put into the array that you then sort.
/* This Program is the main entry point
* in order to call insertion_sort
*/
#include <insertion_sort.cpp>
#include <utils.hpp>
#include <iostream>
#include <fstream>
#include <sstream>
#include <stdlib.h>
using namespace std;
int main(int argc, char const *argv[])
{
/**
* YOUR CODE HERE
* 1. Check for the number of arguments.
* Only proceed if the number of argument is correct,
* We will only check for ./main [INPUT_FILE] [OUTPUT_FILE]
*
*/
if(argc == 3){
/**
* YOUR CODE HERE
* 2. Read the file [INPUT_FILE]
*
*/
ifstream fin;
ofstream fout;
fin.open(argv[1]);
if (!fin.is_open()){
return -1;
}
string line;
string line2;
getline(fin, line);
getline(fin, line2);
int size = atoi(&line.at(0));
int iterator = 0;
/**
* YOUR CODE HERE
* 3. Build IntSequence
*/
IntSequence unsorted_array;
unsorted_array.length = size;
unsorted_array.array = new int[unsorted_array.length];
for (unsigned int i = 0; i < line2.length(); i++){
if (&line2.at(i) != " "){
unsorted_array.array[iterator] = atoi(&line2.at(i));
iterator += 1;
}
/**
* YOUR CODE HERE
* 4. Run Insertion Sort
*/
insertion_sort(unsorted_array);
/**
* YOUR CODE HERE
* 5. Write the file into [OUTPUT_FILE]
*/
fout.open(argv[2]);
if (fout.is_open()){
for (unsigned int i = 0; i < unsorted_array.length; i++){
fout << unsorted_array.array[i] << " ";
}
} else {
return -1;
}
}
fin.close();
fout.close();
return 0;
} else {
return -1;
}
}

In this line it seems that you are comparing a char * to another char *.
if (&line2.at(i) != " "){
I think that you intended to compare a char to a char instead, in other words check that the current character is not a space to then convert it to an integer.
if (line2.at(i) != ' '){
Otherwise your expression inside your if statement would likely return true even when you didn't count on it returning true, potentially overflowing your int array due to adding duplicate integers, since atoi ignores whitespace.

Related

Extract fields and values from text line using C++

I am reading in a text file with lines of the format:
date =20170422,line =10,index =3,field =partType,lock =productCode1,bookmark=2/19/56,
I need to extract the name of the field (date, line, index, etc.) and its corresponding value into char field[] and char value[] variables. If necessary, I am allowed to modify the format of the lines.
My initial thinking was to use while loops and check for = and , characters but it was getting messy and it seems like there may be a cleaner way.
You could do something like the below example. Split the string by commas using getline from your file, then split use an istringstream to and getline to split it again by an equals sign.
#include<iostream>
#include<fstream>
#include<string>
#include<sstream>
int main()
{
std::ifstream file("test.txt");
std::string wholeLine, partOfLine;
while(std::getline(file, wholeLine, ',')) {
std::istringstream wholeLineSS(wholeLine);
while(std::getline(wholeLineSS, partOfLine, '=')) {
std::cout<<partOfLine<<std::endl;
}
}
return 0;
}
The program I post here extracts the parameters from one or more strings which are formatted as you require. The function extract extracts all the parameters contained in a string (of the format you specified) and insert their names and values in a structure (struct sParms) array.
You may compile the program as extract and execute it at the system prompt as:
username: ./extract "date =20170422,line =10,index =3,field
=partType,lock =productCode1,bookmark=2/19/56,"
The output will be the following:
[date]=[20170422]
[line]=[10]
[index]=[3]
[field]=[partType]
[lock]=[productCode1]
[bookmark]=[2/19/56]
You may execute the program with more than one string:
username: ./extract "date =20170422,line =10,index =3,field
=partType,lock =productCode1,bookmark=2/19/56," "yes=1, no=0"
The output will be the following:
[date]=[20170422]
[line]=[10]
[index]=[3]
[field]=[partType]
[lock]=[productCode1]
[bookmark]=[2/19/56]
[yes]=[1]
[no]=[0]
In the following line there's the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
//Parameters: date =20170422,line =10,index =3,field =partType,lock =productCode1,bookmark=2/19/56,
#define SEPARATOR ','
#define ASSIGNEMENT '='
typedef struct sParms {
char * fieldName;
char * fieldValue;
} tsParms;
int loadString(char *to, const char *from);
int extract(tsParms **oparms, const char *inb);
// Retrieve buffer length
int loadString(char *to, const char *from)
{
int len=0;
while(*from<=32 && *from!=SEPARATOR && *from!=ASSIGNEMENT)
from++;
// Get the string value
while(*from>32 && *from!=SEPARATOR && *from!=ASSIGNEMENT) {
*(to+len++)=*from;
++from;
}
*(to+len++)=0;
return len;
}
int extract(tsParms ** oparms, const char *inb)
{
int cnt=0,j;
const char * end, *equ, *start;
char * buff;
tsParms * parms;
if (inb == NULL || strlen(inb) == 0 || oparms == NULL)
return 0;
// It counts the number of parms
end=strchr(inb,ASSIGNEMENT);
while(end) {
cnt++;
end=strchr(end+1,ASSIGNEMENT);
}
if (!cnt)
return 0;
/* Doing some considerations we may assume that the memory to use to store
* fields name and values is the same of the input string (inb)
*
* The space to store the pointers is cnt * sizeof(tsParms *).
*/
j=cnt * sizeof(tsParms) + strlen(inb);
parms = malloc(j+1);
memset(parms,0,j+1);
buff = (char *)(parms+cnt); // The memory area where we can save data!
start=inb;end=start;cnt=0;
do {
end=strchr(start,SEPARATOR);
equ=strchr(start,ASSIGNEMENT);
if (equ) {
//Get the field name
parms[cnt].fieldName=buff;
buff+=loadString(buff,start);
//Get the field value
start=equ+1;
parms[cnt].fieldValue=buff;
buff+=loadString(buff,start);
cnt++;
}
if (end)
start=end+1;
} while(end);
*oparms = parms;
return cnt;
}
int main(int argc, char *argv[])
{
int i,j,cnt=0,retval=0;
tsParms * parms=NULL;
if (argc<2) {
printf("Usage: %s \"string-1\" [\"string-2\" ...\"string-n\"]\n",basename(argv[0]));
return 1;
}
for(i=1; i<argc; i++) {
cnt=extract(&parms, argv[i]);
if (cnt!=0 && parms!=NULL) {
for(j=0;j<cnt;j++) {
printf("[%s]=[%s]\n",parms[j].fieldName,parms[j].fieldValue);
}
puts("");
free((void *)parms);
} else {
retval=1;
break;
}
}
return retval;
}

Pointing to a specific element in a character array

I've been trying to bend my head around this problem for a week now, but I can't seem to find anything online and I've given up on trying to solve it on my own.
My assignment is to write a program which will read names from a file and accept new entries from the user, then sort the entires and write them out to the file. The only crux about this is that I have to sort them in a function and use pointers to do so. This code is supposed to be written in C++ aswell, using character arrays.
The code I have right now looks like this. This is a working version, the only problem is that I don't use neither pointers or a function to sort the names.
#include<iostream>
#include<cstdlib>
#include<fstream>
#include<cstring>
bool sorted;
using namespace std;
int main()
{
int i = 0;
int numNames = 0;
ifstream ifs;
ifs.open("namn.txt");
char c[20][20];
if(ifs.is_open())
{
while(!ifs.eof())
{
ifs >> c[i];
i++;
}
}
cout<<"How many names do you want to enter?"<<endl;
cin>>numNames;
for(int l = i-1; l<numNames+i-1; l++)
{
system("cls");
cout<<"Enter a name: ";
cin>>c[l];
}
while(sorted == false)
{
for(int j = 0; j<numNames+i-1; j++)
{
for(int k = j; k<numNames+i-1; k++)
{
if(c[j][0] > c[k][0])
{
char snorre[20];
strcpy(snorre,c[j]);
strcpy(c[j],c[k]);
strcpy(c[k],snorre);
}
else if(c[j][0] == c[k][0])
{
if(c[j][1] > c[k][1])
{
char snorre[20];
strcpy(snorre,c[j]);
strcpy(c[j],c[k]);
strcpy(c[k],snorre);
}
}
}
}
cout<<endl<<endl<<endl;
ofstream ofs;
ofs.open("namn.txt");
for(int o = 0; o<numNames+i-1; o++)
{
cout<<c[o]<<" ";
ofs<<c[o]<<endl;
}
ofs.close();
system("pause");
sorted = true;
}
}
So hopefully someone could help me out with this problem, thanks in advance! :)
To get your code to use pointers and functions, you can do this- you should change your code and make it use the following:
First, Get each name from the file to an std::string, using getline(ifstream_object, std::string_object), for reference see here.
Convert each one to a const char * (also shown in that example), using .c_str().
Do the following to each of the new names entered.
Store all names entered in this array pointers: char *names[20];, like this: names[i] = name;
Next, Create a function such as follows:
int location_of_bigger_string(const char* s1, const char* s2)
{
// Returns 1 if s1 should be before s2 and 2 otherwise
// This way, you use functions and pointers together.
// Use strcmp(s1,s2) here to determine returning value
}
strcmp(char*, char*) - read about it here.
Finally, to sort all the strings, use qsort or this example.
Here's the complete code,
Note that the compare function gets pointers to the elements, here the elements are pointers themselves, so what's passed to "compare" function is of type "char **"
{
#include "stdafx.h"
#include<iostream>
//retruns +1 if str1 > str2 alphabetically
int compare(const void * a, const void * b )
{
const char * str1 = *((const char **)a);
const char * str2 = *((const char **)b);
int i;
for ( i = 0 ; str1[i] && str2[i] ; i++ )
{
if ( str1[i] > str2[i] )
{
return +1;
}
else if ( str1[i] < str2[i] )
{
return -1;
}
}
//one or both strings have ended
if (str1[i]) //str1 is longer
return +1;
else if (str2[i]) //str2 is longer
return -1;
else
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
char * names[]={"Zebra","Kousha","Koosha","Kou","Koush","Test"};
qsort( names, 6, sizeof(char *), compare );
return 0;
}
}

Reading number list from file to a dynamic array

I'm having trouble reading a number list from a .txt file to a dynamic array of type double. This first number in the list is the number of numbers to add to the array. After the first number, the numbers in the list all have decimals.
My header file:
#include <iostream>
#ifndef SORT
#define SORT
class Sort{
private:
double i;
double* darray; // da array
double j;
double size;
public:
Sort();
~Sort();
std::string getFileName(int, char**);
bool checkFileName(std::string);
void letsDoIt(std::string);
void getArray(std::string);
};
#endif
main.cpp:
#include <stdio.h>
#include <stdlib.h>
#include "main.h"
int main(int argc, char** argv)
{
Sort sort;
std::string cheese = sort.getFileName(argc, argv); //cheese is the file name
bool ean = sort.checkFileName(cheese); //pass in file name fo' da check
sort.letsDoIt(cheese); //starts the whole thing up
return 0;
}
impl.cpp:
#include <iostream>
#include <fstream>
#include <cstring>
#include <stdlib.h>
#include "main.h"
Sort::Sort(){
darray[0];
i = 0;
j = 0;
size = 0;
}
Sort::~Sort(){
std::cout << "Destroyed" << std::endl;
}
std::string Sort::getFileName(int argc, char* argv[]){
std::string fileIn = "";
for(int i = 1; i < argc;)//argc the number of arguements
{
fileIn += argv[i];//argv the array of arguements
if(++i != argc)
fileIn += " ";
}
return fileIn;
}
bool Sort::checkFileName(std::string userFile){
if(userFile.empty()){
std::cout<<"No user input"<<std::endl;
return false;
}
else{
std::ifstream tryread(userFile.c_str());
if (tryread.is_open()){
tryread.close();
return true;
}
else{
return false;
}
}
}
void Sort::letsDoIt(std::string file){
getArray(file);
}
void Sort::getArray(std::string file){
double n = 0;
int count = 0;
// create a file-reading object
std::ifstream fin;
fin.open(file.c_str()); // open a file
fin >> n; //first line of the file is the number of numbers to collect to the array
size = n;
std::cout << "size: " << size << std::endl;
darray = (double*)malloc(n * sizeof(double)); //allocate storage for the array
// read each line of the file
while (!fin.eof())
{
fin >> n;
if (count == 0){ //if count is 0, don't add to array
count++;
std::cout << "count++" << std::endl;
}
else {
darray[count - 1] = n; //array = line from file
count++;
}
std::cout << std::endl;
}
free((void*) darray);
}
I have to use malloc, but I think I may be using it incorrectly. I've read other posts but I am still having trouble understanding what is going on.
Thanks for the help!
Your use of malloc() is fine. Your reading is not doing what you want it to do.
Say I have the inputfile:
3
1.2
2.3
3.7
My array would be:
[0]: 2.3
[1]: 3.7
[2]: 0
This is because you are reading in the value 1.2 as if you were rereading the number of values.
When you have this line:
fin >> n; //first line of the file is the number of numbers to collect to the array
You are reading in the count, in this case 3, and advancing where in the file you will read from next. You are then attempting to reread that value but are getting the first entry instead.
I believe that replacing your while() {...} with the code below will do what you are looking for.
while (count != size && fin >> n)
{
darray[count++] = n; //array = line from file
std::cout << n << std::endl;
}
This should give you the correct values in the array:
[0]: 1.2
[1]: 2.3
[2]: 3.7
You appear to be writing the next exploitable program. You are mistakenly trusting the first line of the file to determine your buffer size, then reading an unlimited amount of data from the remainder of the file into a buffer that is not unlimited. This allows an evil input file to trash some other memory in your program, possibly allowing the creator of that file to take control of your computer. Oh noes!
Here's what you need to do to fix it:
Remember how much memory you allocated (you'll need it in step #2). Have a variable alleged_size or array_length that is separate from the one you use to read the rest of the data.
Don't allow count to run past the end of the array. Your loop should look more like this:
while ((count < alleged_size) && (cin >> n))
This both prevents array overrun and decides whether to process data based on whether it was parsed successfully, not whether you reached the end-of-file at some useless point in the past.
The less problematic bug is the one #bentank noticed, that you didn't realize that you kept your position in the file, which is after the first line, and shouldn't expect to hit that line within the loop.
In addition to this, you probably want to deallocate the memory in your destructor. Right now you throw the data away immediately after parsing it. Wouldn't other functions like to party on that data too?

I get a number 2 when I reverse my string

I wrote this code to reverse strings. It works well, but when I enter short strings like "american beauty," it actually prints "ytuaeb nacirema2." This is my code. I would like to know what is wrong with my code that prints a random 2 at the end of the string. Thanks
// This program prompts the user to enter a string and displays it backwards.
#include <iostream>
#include <cstdlib>
using namespace std;
void printBackwards(char *strPtr); // Function prototype
int main() {
const int SIZE = 50;
char userString[SIZE];
char *strPtr;
cout << "Please enter a string (up to 49 characters)";
cin.getline(userString, SIZE);
printBackwards(userString);
}
//**************************************************************
// Definition of printBackwards. This function receives a *
// pointer to character and inverts the order of the characters*
// within it. *
//**************************************************************
void printBackwards(char *strPtr) {
const int SIZE = 50;
int length = 0;
char stringInverted[SIZE];
int count = 0;
char *strPtr1 = 0;
int stringSize;
int i = 0;
int sum = 0;
while (*strPtr != '\0') {
strPtr++; // Set the pointer at the end of the string.
sum++; // Add to sum.
}
strPtr--;
// Save the contents of strPtr on stringInverted on inverted order
while (count < sum) {
stringInverted[count] = *strPtr;
strPtr--;
count++;
}
// Add '\0' at the end of stringSize
stringInverted[count] == '\0';
cout << stringInverted << endl;
}
Thanks.
Your null termination is wrong. You're using == instead of =. You need to change:
stringInverted[count] == '\0';
into
stringInverted[count] = '\0';
// Add '\0' at the end of stringSize
stringInverted[count] == '\0';
Should use = here.
What is wrong with your code is that you do not even use strlen for counting the length of the string and you use fixed size strings (no malloc, or, gasp new[]), or the std::string (this is C++)! Even in plain C, not using strlen is always wrong because it is hand-optimized for the processor. What is worst, you have allocated the string to be returned (stringInverted) from the stack frame, which means when the function exits, the pointer is invalid and any time the code "works" is purely accidental.
To reverse a string on c++ you do this:
#include <iostream>
#include <string>
int main() {
std::string s = "asdfasdf";
std::string reversed (s.rbegin(), s.rend());
std::cout << reversed << std::endl;
}
To reverse a string in C99 you do this:
char *reverse(const char *string) {
int length = strlen(string);
char *rv = (char*)malloc(length + 1);
char *end = rv + length;
*end-- = 0;
for ( ; end >= rv; end --, string ++) {
*end = *string;
}
return rv;
}
and remember to free the returned pointer after use. All other answers so far are blatantly wrong :)

Issues with flushing cout after getting file data

I am trying to write an implementation of rc4. I am reading in plaintext from a file using an ifstream. I noticed that it wasn't outputting at the end of the file, so I tried the various ways of explicitly clearing the buffers. No matter which way (using an endl, appending \n, calling cout.flush()) I try to flush the buffer, I get a segfault. As a sanity check, I replaced my code with an example from the web, which I also tested separately. It works if I put it in its own file and compile it (e.g., it prints out the contents of the file, doesn't segfault, and doesn't require any calls to flush() or endl to do so), but not in my code.
Here is the offending bit of code (which works fine outside of my code; its copied pretty much directly from cplusplus.com)
ifstream is;
is.open("plain");
char c;
while (is.good()) // loop while extraction from file is possible
{
c = is.get(); // get character from file
if (is.good())
cout << c;
// cout.flush();
}
is.close(); // close file*/
Here is the full code: (warning, lots of commented out code)
#include <iostream>
#include <fstream>
#include <string.h>
#include <vector>
using namespace std;
static char s[256], k[256];
//static char *i, *j;
void swap(int m, int n, char t[256]){
char tmp = t[m];
t[m] = t[n];
t[n] = tmp;
}
char getByte(){
static char i(0), j(0);
i = (i+1)%256;
j = (j + s[i])%256;
swap(i, j, s);
return s[(s[i]+s[j]) % 256];
}
int main(int argc, char ** argv){
/*string key = argv[1];*/
if(argc < 4){
cout << "Usage: \n rc4 keyfile plaintextfile outputfile" << endl;
return -1;
}
string key;
ifstream keyfile (argv[1]);
keyfile >> k;
cout << "Key = " << k << endl;
keyfile.close();
/*ifstream plaintextf;
plaintextf.open(argv[2]);*/
ofstream ciphertextf (argv[3]);
for(int q = 0; q < 256; q++){
s[q] = q;
}
int i, j;
for(int m = 0; m < 256; m++){
j = (j + s[m] + k[m % sizeof(k)])%256;
swap(m, j, s);
}
// vector<char> bytes(plaintext.begin(), plaintext.end());
// bytes.push_back('\0');
// vector<char>::iterator it = bytes.begin();
/* char pt;
while(plaintextf.good()){
pt = plaintextf.get();
if(plaintextf.good()){
cout << pt;
ciphertextf <<(char) (pt ^ getByte());
}
} */
ifstream is;
is.open("plain");
char c;
while (is.good()) // loop while extraction from file is possible
{
c = is.get(); // get character from file
if (is.good())
cout << c;
// cout.flush();
}
is.close(); // close file*/
/*// plaintextf.close();
ciphertextf.close();
keyfile.close();
*/
return 0;
}
Additionally, I think the second call to is.good() [ as in if(is.good()) ], would prevent the very last character of the file from being copied.