c++ strtok problem - c++

i'm trying to create a map of word==>drow, like polindrom...
the problem is at the final level at "strtok"...
first i split it, then in subsequent call when doing strtok(NULL," "); it works ok.
the problem is when i add the second string "poly_buffer"... seems it works on it....
#include "stdafx.h"
#include <iostream>
#include <cstdio>
#include <string>
#include <map>
#include <string>
using namespace std;
void poly(char *buffer)
{
char temp;
for (int i=0; i<=strlen(buffer); i++)
{
int word_start = i, word_stop = i;
while (buffer[i] != 32 && buffer[i] != '\0') { i++; word_stop++; }
word_stop--;
//swap chars until the middle of word
while (word_stop >= word_start)
{
//swap the chars
temp = buffer[word_stop];
buffer[word_stop] = buffer[word_start];
buffer[word_start] = temp;
word_stop--;
word_start++;
}
word_start = i;
}
}
void main()
{
FILE *fp;
char *buffer;
char *poly_buffer;
long file_size;
map<string,string> map_poly;
fp = fopen("input.txt", "r");
if (fp == NULL) { fputs("File Error",stderr); exit(1); }
//get file size
fseek(fp,1,SEEK_END);
file_size = ftell(fp);
rewind(fp);
//allocate memory
buffer = new char[file_size+1];
poly_buffer = new char[file_size+1];
//get file content into buffer
fread(buffer,1, file_size,fp);
strcpy(poly_buffer,buffer);
buffer[file_size] = '\0';
poly_buffer[file_size] = '\0';
poly(buffer);
buffer = strtok(buffer," ");
poly_buffer = strtok(poly_buffer," ");
while (buffer != NULL)
{
map_poly[buffer] = poly_buffer;
printf("%s ==> %s\n", buffer, poly_buffer);
buffer = strtok(NULL," ");
poly_buffer = strtok(NULL," ");
}
fclose(fp);
while(1);
}
what am i doing wrong ?

the both strtok calls
buffer = strtok(buffer, " ");
poly_buffer = strtok(poly_buffer," ");
are interfering with each other, you need to process them one by one - you cannot do them at the same time because they are sharing static memory in the runtime library. i.e. first do strtok(buffer," ") strtok(NULL, " ") until end, then do strtok( poly_buffer, " ")///
see runtime reference doc for strtok

If you are using C++, why on Earth would you use strtok? Use a stringstream to tokenise and a vector to contain the words:
#include <string>
#include <sstream>
#include <iostream>
#include <vector>
using namespace std;
int main() {
istringsream is( "here are some words" );
string word;
vector <string> words;
while( is >> word ) {
words.push_back( word );
}
for ( unsigned int i = 0; i < words.size(); i++ ) {
cout << "word #" << i << " is " << words[i] << endl;
}
}

From the man page for strtok, strtok_r:
"Avoid using these functions."

Related

How to use mmap for integer input?

I have coded a program that uses mmap as input to fill a integer 2D vector from a .txt file. The code is part of a larger program and will be submitted to a competition. Is there a way to improve the speed using mmap, or by using a different way all together? Here is the code:
#include <fstream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <iostream>
// for mmap:
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
using namespace std;
const char* map_file(const char* fname, size_t& length);
int main()
{
auto start = std::chrono::high_resolution_clock::now();
size_t length;
auto f = map_file("erasmus.in", length);
auto l = f + length;
int i = 0;
bool flag = false;
string lines;
vector<vector<int> > students(10000); //The number of lines is predefined
const char* temp;
while (f && f!=l) {
string element = "";
temp = static_cast<const char*>(memchr(f, '\n', l-f));
for(f = f; f<=temp; f++)
{
if(!isspace(*f))
{
element += *f;
flag = true;
}
if(isspace(*f) && flag == true)
{
flag = false;
int assigned_element = stoi(element);
students[i].push_back(assigned_element);
element = "";
}
}
i++;
temp++;
}
auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed1 = finish - start;
FILE* output = fopen("erasmus.out", "w");
for (int i = 0; i < students.size(); i++)
{
for (int j = 0; j < students[i].size(); j++)
{
fprintf(output, "%d ", students[i][j]);
}
fprintf(output, "\n");
}
std::cout << "Elapsed time: " << elapsed1.count() << " s\n";
return 0;
}
void handle_error(const char* msg) {
perror(msg);
exit(255);
}
const char* map_file(const char* directory, size_t& length)
{
int fileDirectory = open(directory, O_RDONLY);
if (fileDirectory == -1)
handle_error("open");
// obtain file size
struct stat sb;
if (fstat(fileDirectory, &sb) == -1)
handle_error("fstat");
length = sb.st_size;
const char* map = static_cast<const char*>(mmap(NULL, length, PROT_READ, MAP_PRIVATE, fileDirectory, 0u));
if (map == MAP_FAILED)
handle_error("mmap");
return map;
}
The file will be executed on a linux system, if this helps to find the optimal answer. At the end of each line of the .txt
there is a space character (' ') and a newline('\n')

Segmentation fault (core dumped), storing char * to string vector of struct

#include <iostream>
#include <fstream>
#include <string.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <semaphore.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <vector>
#include <sstream>
#define SHMSIZE 1024
using namespace std;
namespace patch
{
template < typename T > std::string to_string( const T& n )
{
std::ostringstream stm ;
stm << n ;
return stm.str() ;
}
}
struct process
{
int r;
string name;
vector<string> lines;
};
int main(int argc, char * argv[])
{
int firstRun = 1; //Skipping First Line of Assign-1.ip.
int quantum = 0; //For taking input of quantum.
int count = 0; //For number of processes.
int pchtoint;
string c;
char * pch; //For tokenization.
string reading_file; //Reading a line from file.
char * readarr; //Converting "reading_file" to readarr for tokenization.
process * p;
//=== Quantum Input ===//
cout<<"Enter Quantum size [1-1000]: ";
cin>>quantum;
while(quantum < 1 || quantum > 1000)
{
cout<<"Wrong input!!! Enter Again [1-1000]: ";
cin>>quantum;
}
//=====================//
//===Filing===//
ifstream read("Assign-2.ip");
if(read.is_open())
{
while(!read.eof())
{
getline(read, reading_file);
readarr = new char[reading_file.size() + 1];
for(int i = 0; i < reading_file.length(); i++)
{
readarr[i] = reading_file[i];
}
if(firstRun > 1)
{
int countingline = 0; //counting the number of lines in a process.
pch = strtok (readarr," ,");
while (pch != NULL)
{
c = pch[1];
pchtoint = atoi(c.c_str());
p[pchtoint-1].r++;
p[pchtoint-1].lines.push_back(pch);
for(int i = 0; i < p[pchtoint-1].lines.size(); i++)
cout<<p[pchtoint-1].name<<"=="<<p[pchtoint-1].lines.at(i)<<endl;
pch = strtok (NULL, " ,");
}
}
else
{
pch = strtok (readarr,",.-");
while (pch != NULL)
{
count++;
pch = strtok (NULL, ",.-");
}
p = new process[count];
string s = "p";
for(int i = 0; i < count; i++)
{
s = s + patch::to_string(i+1);
p[i].name = s;
s = s[0];
}
firstRun++;
}
}
}
else
{
cout<<"Cannot open file!!!"<<endl;
}
read.close();
return 0;
}
Enter Quantum size [1-1000]: 2
p1==p1-l1
p2==p2-l1
p3==p3-l1
p1==p1-l1
p1==p1-l2
p2==p2-l1
p2==p2-l2
p3==p3-l1
p3==p3-l2
p1==p1-l1
p1==p1-l2
p1==p1-l3
p3==p3-l1
p3==p3-l2
p3==p3-l3
p1==p1-l1
p1==p1-l2
p1==p1-l3
p1==p1-l4
Segmentation fault (core dumped)
I am reading data from a cvs file. and storing it in struct that is p here. but I don't know why it is giving segmentation fault. I am compiling it on ubuntu terminal.
The input file contains data:
P1, P2, P3,
p1-l1, p2-l1, p3-l1
p1-l2, p2-l2, p3-l2
p1-l3, , p3-l3
p1-l4, ,

error: too few arguments to function 'std::vector

I am getting a compile error when I try to access my function
The program retrieves data from 2 different source and is supposed to come together in that one function.
k.cpp: In function 'int main()':
k.cpp:65:10: error: too few arguments to function 'std::vector<std::basic_string<char> > buymngr(FILE*)'
k.cpp:45:26: note: declared here
It is indicating that I am missing a parameter here -> std::vector buymngr(FILE *buyfp)
I am just very unsure of what it is asking for.
#include <cstdio>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <unistd.h>
#include <cstring>
#include <cstdlib>
#include <vector>
using namespace std;
FILE *init( const char *fname ){
FILE *buyfp = popen( fname, "r" );
return buyfp;
}
vector<string> getmyData()
{
FILE *fp = popen("php orders.php 155", "r");
if (fp == NULL) perror ("Error opening file");
char buff[BUFSIZ];
vector<string> vrecords;
while(fgets(buff, sizeof(buff), fp) != NULL){
size_t n = strlen(buff);
if (n && buff[n - 1] == '\n') buff[n - 1] = '\0';
if (buff[0] != '\0') vrecords.push_back(buff);
}
return vrecords;
}
std::vector<std::string> getmarketbuyData(FILE *buyfp){
char buff2[BUFSIZ];
vector<std::string> vrecs;
while(std::fgets(buff2, sizeof buff2, buyfp) != NULL){
size_t n = std::strlen( buff2 );
if ( n && buff2[n-1] == '\n' ) buff2[n-1] = '\0';
if ( buff2[0] != '\0' ) vrecs.push_back( buff2 );
}
for(int t = 0; t < vrecs.size(); ++t){
cout << vrecs[t] << " " << endl;
}
return vrecs;
}
std::vector<std::string> buymngr(FILE *buyfp){
vector<std::string> buydat;
vector<std::string> markdat;
buyfp = init("php buyorders.php 155");
if (buyfp == NULL) perror ("Error opening file");
if ( buyfp ){
buydat = getmarketbuyData( buyfp );
}
for(int b = 0; b < sizeof(buydat); ++b){
cout << buydat[b] << " " << endl;
}
markdat = getmyData();
for(int l = 0; l < sizeof(markdat); ++l){
cout << markdat[l] << " " << endl;
}
}
//Le Main
int main(void)
{
buymngr(FILE*);
}
How do I get rid of the error? What parameter is it asking for?
Your definition goes like:-
std::vector<std::string> buymngr(FILE *buyfp)
so it's expecting FILE* type as its argument whereas you're calling it:-
buymngr();
without any arguments.

I can't token my char how can I get there?

using namespace std;
char *fx[65537];
void main()
{
FILE *fp;
int i = 0;
int c = 0;
char *token = NULL;
char str1[] = " ";
fp = fopen("fx.txt", "r");
char s[51];
for (c = 0; i <= 65536; c++)
{
token = strtok(fx[c], str1);
while (token != NULL)
{
printf("token : %s", token);
putchar('\n');
token = strtok(NULL, str1);
}
}
while (!feof(fp))
{
i = i++;
fgets(s, 50, fp);
fx[i] = s; //fx 포인터에 s의 임시배열 저장
}
fclose(fp);
}
Hello
I want make a program that read the *.txt file with one line and save char pointer
and I token this char and save
For example
there txt
test.txt
123 654 8765 4213
321 565 4687 8765
652 126 6874 3215
then,
char *a[3] = {123 654 8765 4213, 321 565 4687 8765, 652 126 6874 3215};
char b[3][4];
char b[0][] = {123, 654, 8765, 4213};
char b[1][] = {321, 565, 4687, 8765};
char b[2][] = {652, 126, 6874, 3215};
But I don't know how to that :(
Can you help me?
use vector and string
#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
#include <string>
int main() {
std::ifstream input("fx.txt");
std::vector<std::string> v((std::istream_iterator<std::string>(input)),std::istream_iterator<std::string>());
for ( std::vector<std::string>::const_iterator iter = v.begin();iter != v.end(); ++iter ) {
std::cout << *iter << std::endl;//print by iterator
}
for(int i=0;i<v.size();++i)
std::cout << v[i] << std::endl;//print by []
}
By C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *fx[65537];
int main(){
FILE *fp;
int i = 0, j;
int c = 0;
char *token = NULL;
char str1[] = " \n";
char s[51];
fp = fopen("fx.txt", "r");
while (fgets(s, sizeof(s), fp)){
token = strtok(s, str1);
while (token != NULL) {
fx[i++] = strdup(token);
if(i == 65537)
break;
token = strtok(NULL, str1);
}
}
fclose(fp);
c = i;
for(i=0;i<c;++i)
printf("%s ", fx[i]);
printf("\n\n");
char *(*b)[4] = (char *(*)[4])fx;
for(i=0;i<3;++i){
for(j=0;j<4;++j)
printf("%s ", b[i][j]);
printf("\n");
}
//deallocation
for(i=0;i<c;++i)
free(fx[i]);
return 0;
}
If there are no restrictions, use strings, get boost and then you can use
vector<string>splitString;
boost::split(splitString,a[i],boost::is_any_of(" "));
this way each element in your string vector (splitString) will contain one "number" of the ith line.

Child doesn't terminate correctly in fork

I am writing a c program for a class that is a small shell. The user inputs a command, and the code executes it using the exec() function.
I need to have a fork in the process so all the work is done in the child process. The only problem is that the child won't terminate properly and execute the command. When I run the code without the fork, it executes commands perfectly.
The problem seems to be coming from where I am creating the string to be used in the execv call. It's the line of code where I call strcpy. If I comment that out, things work fine. I also tried changing it to strncat with the same problem. I'm clueless as to what's causing this and welcome any help.
#include <sys/wait.h>
#include <vector>
#include <sstream>
#include <cstdlib>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <unistd.h>
using namespace std;
string *tokenize(string line);
void setCommand(string *ary);
string command;
static int argument_length;
int main() {
string argument;
cout << "Please enter a unix command:\n";
getline(cin, argument);
string *ary = tokenize(argument);
//begin fork process
pid_t pID = fork();
if (pID == 0) { // child
setCommand(ary);
char *full_command[argument_length];
for (int i = 0; i <= argument_length; i++) {
if (i == 0) {
full_command[i] = (char *) command.c_str();
// cout<<"full_command " <<i << " = "<<full_command[i]<<endl;
} else if (i == argument_length) {
full_command[i] = (char *) 0;
} else {
full_command[i] = (char *) ary[i].c_str();
// cout<<"full_command " <<i << " = "<<full_command[i]<<endl;
}
}
char* arg1;
const char *tmpStr=command.c_str();
strcpy(arg1, tmpStr);
execv((const char*) arg1, full_command);
cout<<"I'm the child"<<endl;
} else if (pID < 0) { //error
cout<<"Could not fork"<<endl;
} else { //Parent
int childExitStatus;
pid_t wpID = waitpid(pID, &childExitStatus, WCONTINUED);
cout<<"wPID = "<< wpID<<endl;
if(WIFEXITED(childExitStatus))
cout<<"Completed "<<ary[0]<<endl;
else
cout<<"Could not terminate child properly."<<WEXITSTATUS(childExitStatus)<<endl;
}
// cout<<"Command = "<<command<<endl;
return 0;
}
string *tokenize(string line) //splits lines of text into seperate words
{
int counter = 0;
string tmp = "";
istringstream first_ss(line, istringstream::in);
istringstream second_ss(line, istringstream::in);
while (first_ss >> tmp) {
counter++;
}
argument_length = counter;
string *ary = new string[counter];
int i = 0;
while (second_ss >> tmp) {
ary[i] = tmp;
i++;
}
return ary;
}
void setCommand(string *ary) {
command = "/bin/" + ary[0];
// codeblock paste stops here
You said:
Its the line of code where I call
strcpy.
You haven't allocated any memory to store your string. The first parameter to strcpy is the destination pointer, and you're using an uninitialized value for that pointer. From the strcpy man page:
char *strcpy(char *s1, const char *s2);
The stpcpy() and strcpy() functions copy the string s2 to s1 (including
the terminating `\0' character).
There may be other issues, but this is the first thing I picked up on.