Adding values to char* var from txt file - c++

Example file:
[16bpp] Ponete el cinturon *-*
arfield
Nothing (cumpleanios):
Alkon^
~~|Tampon)
[16bpp] Chico Tonto.
Budin
16bpp] Leooooooooo!!!!!
Ev
16bpp] fedee
etamod
:) mAnKeAno
I want each name on a different array position...
I tried this code:
int c;
FILE *file;
file = fopen("bots.txt", "r");
if (file){
char *buffer;
char *jugadores = new char[1000];
int p;
int pos;
while ((c = getc(file)) != EOF){
if (c == '\n'){
strcpy(jugadores[p], buffer);
p++;
buffer = "";
pos = 0;
} else {
buffer[pos] = c;
pos++;
}
}
fclose(file);
}
But it doesn't even compile...
In php the right code would be something like this:
$data = file_get_contents("file.txt");
$names = explode("\n", $data);

Your code has several flaws in it. You need something more like this instead:
FILE *file = fopen("bots.txt", "r");
if (file)
{
char** lines = new char*[1000];
int maxlines = 1000;
int numlines = 0;
char *buffer = new char[1024];
int maxbuf = 1024;
int buflen = 0;
char *line;
int c;
while ((c = getc(file)) != EOF)
{
if (c == '\n')
{
if (numlines == maxlines)
{
char** tmplines = new char*[maxlines+1000];
memcpy(tmplines, lines, sizeof(char*)*maxlines);
delete[] lines;
lines = tmplines;
maxlines += 1000;
}
line = new char[buflen+1];
memcpy(line, buffer, sizeof(char)*buflen);
line[buflen] = 0;
lines[numlines] = line
numlines++;
buflen = 0;
}
else
{
if (buflen == maxbuf)
{
char* tmpbuf = new char[maxbuf+1024];
memcpy(tmpbuf, buffer, sizeof(char)*maxbuf);
delete[] buffer;
buffer = tmpbuf;
maxbuf += 1024;
}
buffer[buflen] = c;
buflen++;
}
}
fclose(file);
if (buflen > 0)
{
if (numlines == maxlines)
{
char** tmplines = new char*[maxlines+1000];
memcpy(tmplines, lines, sizeof(char*)*maxlines);
delete[] lines;
lines = tmplines;
maxlines += 1000;
}
line = new char[buflen+1];
memcpy(line, buffer, sizeof(char)*buflen);
line[buflen] = 0;
lines[numlines] = line
numlines++;
}
delete[] buffer;
// use lines up to numlines elements as needed...
for (int i = 0; i < numlines; i++)
printf("%s\n", lines[i]);
for (int i = 0; i < numlines; ++i)
delete[] lines[i];
delete[] lines;
}
With that said, since you are using C++, you should use C++ classes that will help manage everything for you. Try something more like this instead:
#include <fstream>
#include <ostream>
#include <string>
#include <vector>
std::ifstream file("bots.txt");
if (file.is_open())
{
std::string line;
std::vector<std::string> lines;
while (std::getline(file, line))
lines.push_back(line);
file.close();
// use lines as needed...
for (int i = 0; i < lines.size(); i++)
std::cout << lines[i] << std::endl;
}

Related

How gets size of char[] when i read from a text file

I'm reading a .txt file. I need to read at most 254 characters into my char* buffer, so I did this:
char *buffer = new char[255];
***Some Code***
if (!feof(fichero))
{
if (fgets(buffer, 254, fichero) != NULL)
{
How do get the size of the buffer read? Right now I'm using a manual method to find '\n' and use its position as the size. But is there a better way?
My code for now:
char *buffer = new char[255];
int tamanio;
***more code***
if (!feof(fichero))
{
if (fgets(buffer, 254, fichero) != NULL)
{
//printarCadena(buffer);
tamanio = limpiarBuffer(buffer);
printf("Tamanio buffer: %i \n", tamanio);
int Gestor::limpiarBuffer(char* buffer)
{
int i;
for(i = 0; i < int(strlen(buffer));i++)
{
if(buffer[i] == '\n')
return i;
}
return int(strlen(buffer) - 1);
}
Edit: I`ve to use Char*, University vibes
Edit2: I've to read line by line, if line ve more than 255 characteres, i read as 2 or more lines
int getSize(char* buffer)
{
int i;
for(i = 0; i < int(strlen(buffer));i++)
{
if(buffer[i] == '\n')
return i;
}
return strlen(buffer);
}
By now no other way to do with char*

How does one locate a pointer error?

I am attempting to create a program to create a Markov chain but I am having pointer problems. When I run the Program I get a segmentation fault.
#include <stdio.h>
#include <cstring>
#include <cstdlib>
struct word;
struct nextword
{
word* sourceword;
word* next = 0;
};
int wordcount;
struct word
{
char* wordstr;
struct word* next = 0;
nextword* followingword = 0;
int nextwordcount = 0;
};
int main()
{
word* firstword = 0;
char * buffer = 0;
long length;
FILE * f = fopen ("alice.txt", "rb");
if (f)
{
fseek (f, 0, SEEK_END);
length = ftell (f);
fseek (f, 0, SEEK_SET);
buffer = (char *)malloc (length);
if (buffer)
{
fread (buffer, 1, length, f);
}
fclose (f);
}
if (buffer)
{
char wordbuffer[500];
int fileindex = 0;
while(fileindex < length-1)
{
int wordindex = 0;
while(buffer[fileindex] != ' ')
{
wordbuffer[wordindex] = buffer[fileindex];
wordindex++;
fileindex++;
}
if(wordindex != 0)
{
wordbuffer[wordindex] = '\0';
word* newword = (word*)malloc(sizeof(word));
char* newwordstr = (char*)malloc((strlen(wordbuffer)+1)*sizeof(char));
strcpy(newword->wordstr, newwordstr);
if(!firstword)
{
firstword = newword;
}
else
{
word* testword = firstword;
while(!testword->next)
{
testword = (testword->next);
}
testword->next = newword;
printf(newword->wordstr);
}
}
return 0;
}
}
else
{
return 1;
}
}
I attempted to remove the file reading part and replace it with a hard coded string, but the problem remained.
You might want to read about STL and use a list. Or use a C list, see a couple of examples,
Adding node in front of linklist
How to pop element from tail in linked list?
Trying to make linkedlist in C
Several problems. Fixed some. compiles.
I have annotated the code with places where you need to fix bounds checking, and the big problem was likely the strcpy to the struct word->wordstr uninitialized char*,
#include <stdio.h>
#include <cstring>
#include <cstdlib>
struct word;
struct nextword
{
word* sourceword;
word* next = 0;
};
int wordcount;
struct word
{
char* wordstr; //what do you think this pointer points to?
struct word* next = 0;
nextword* followingword = 0;
int nextwordcount = 0;
};
int main()
{
FILE* fh = NULL;
word* firstword = 0;
char* buffer = 0;
char* fname = "alice.txt";
long length = 0; //you did not initialize length
if ( (fh = fopen ("alice.txt", "rb")) )
{
//why not use fstat to get file size?
//why not use mmap to read file?
fseek (fh, 0, SEEK_END);
length = ftell (fh); //ok, length set here
fseek (fh, 0, SEEK_SET);
if( (buffer = (char *)malloc (length)) )
{
fread (buffer, 1, length, fh);
}
fclose (fh);
}
else
{
printf("error: cannot open %s",fname);
exit(1);
}
printf("read %s, %ld\n",fname,length);
if (!buffer)
{
printf("error: cannot open %s",fname);
exit(1);
//use exit, to return from main() //return 1;
}
//already checked buffer
{
int fileindex = 0;
//put wordbuffer after fileindex, avoids stackoverflow overwrite
char wordbuffer[500]; //500 bytes on stack, initialize?
memset(wordbuffer,0,sizeof(wordbuffer));
while(fileindex < length-1)
{
int wordindex = 0;
//several errors in this line, check for null terminator,
//check for newline, tab, basically any whitespace
//while(buffer[fileindex] != ' ')
while( buffer[fileindex] && buffer[fileindex] != ' ' )
{
wordbuffer[wordindex] = buffer[fileindex];
wordindex++;
fileindex++;
//here is another error, do not overflow your stack based buffer
if( wordindex>sizeof(buffer)-1 ) break; //do not overflow buffer
}
wordbuffer[wordindex] = '\0'; //terminate wordbuffer
//since you chose wordindex signed, you want it > 0
if(wordindex > 0)
{
//use a constructor
word* newword = (word*)malloc(sizeof(word));
//use a constructor
//or just use strdup, since it is just a cstring
char* newwordstr = strdup(wordbuffer);
//no, just set pointer to the above allocated string
//strcpy(newword->wordstr, newwordstr);
newword->wordstr = newwordstr;
if(!firstword)
{
firstword = newword;
}
else
{
word* testword = firstword;
while(!testword->next)
{
testword = (testword->next);
}
testword->next = newword;
printf(newword->wordstr);
}
}
return 0;
}
}
exit(0); //done
}
This compiles and runs without error, you need to look up linked list handling. You should implement a linked list, and then add word elements to list.

ifstream read reading random char for the whole stream

I'm trying to implement the function from listing 5.1 here
but when copying into a buffer with read from a file I just get the same character (Í) for the whole array, where string.txt is a copy and paste from the previous link content.
Here is my code:
#include <iostream>
#include <fstream>
#include <string>
#include <cinttypes>
#include <cstdio>
#include <cstring>
const int block_size = 0x4000; //16KB
int search(char* buffer, int searchLength, char* stringToSearch, int stringToSearchLength) {
char * potentialMatch;
while (searchLength) {
potentialMatch = reinterpret_cast<char *>(memchr(buffer, *stringToSearch, searchLength));
if (potentialMatch == NULL)
break;
if (stringToSearchLength == 1) {
return 1;
} else {
if (!memcmp(potentialMatch + 1, stringToSearch + 1, stringToSearchLength - 1))
return 1;
}
searchLength -= potentialMatch - buffer + 1;
buffer = potentialMatch + 1;
}
return 0;
}
int main(int argc, char* argv[]) {
char *toSearch = "Interpreting Where";
int done = 0;
int found = 0;
char *buffer;
int64_t fileSizeLeft = 0;
std::ifstream myFile("string.txt");
if (!myFile.fail()) {
buffer = new char[block_size];
myFile.seekg(0, std::ios::end); //Get file's size
fileSizeLeft = myFile.tellg();
} else {
std::cout << "Cannot open file" << std::endl;
return 1;
}
int toSearchLength = strlen(toSearch);
int stringLeft = toSearchLength - 1;
int first_time = 1;
while (!done && fileSizeLeft > toSearchLength) {
if (first_time) {
myFile.read(buffer, block_size);
found = search(buffer, block_size, toSearch, toSearchLength);
} else {
memcpy(buffer, buffer + stringLeft, stringLeft);
myFile.read(buffer+stringLeft, fileSizeLeft-stringLeft);
found = search(buffer, block_size, toSearch, toSearchLength);
}
fileSizeLeft = fileSizeLeft - block_size;
first_time = 0;
}
if (found) {
std::cout << "String found" << std::endl;
} else {
std::cout << "String not found" << std::endl;
}
myFile.close();
delete[] buffer;
return 0;
}
I hope you can help me see what I'm doing wrong, thanks!
You are setting myFile's position to ios_base::end with seekg:
myFile.seekg(0, ios::end);
Then trying to read from it:
myFile.read(buffer, block_size);
Clearly no data will be read since myFile is already at ios_base::end. And you'll be reading whatever uninitialized data that was already in buffer
What you probably intended to do was to set your myFile position back to the beginning by doing this before reading:
myFile.seekg(0, ios::beg);

Is there a better way to search a file for a string?

I need to search a (non-text) file for the byte sequence "9µ}Æ" (or "\x39\xb5\x7d\xc6").
After 5 hours of searching online this is the best I could do. It works but I wanted to know if there is a better way:
char buffer;
int pos=in.tellg();
// search file for string
while(!in.eof()){
in.read(&buffer, 1);
pos=in.tellg();
if(buffer=='9'){
in.read(&buffer, 1);
pos=in.tellg();
if(buffer=='µ'){
in.read(&buffer, 1);
pos=in.tellg();
if(buffer=='}'){
in.read(&buffer, 1);
pos=in.tellg();
if(buffer=='Æ'){
cout << "found";
}
}
}
}
in.seekg((streampos) pos);
Note:
I can't use getline(). It's not a text file so there are probably not many line breaks.
Before I tried using a multi-character buffer and then copying the buffer to a C++ string, and then using string::find(). This didn't work because there are many '\0' characters throughout the file, so the sequence in the buffer would be cut very short when it was copied to the string.
Similar to what bames53 posted; I used a vector as a buffer:
std::ifstream ifs("file.bin");
ifs.seekg(0, std::ios::end);
std::streamsize f_size = ifs.tellg();
ifs.seekg(0, std::ios::beg);
std::vector<unsigned char> buffer(f_size);
ifs.read(buffer.data(), f_size);
std::vector<unsigned char> seq = {0x39, 0xb5, 0x7d, 0xc6};
bool found = std::search(buffer.begin(), buffer.end(), seq.begin(), seq.end()) != buffer.end();
If you don't mind loading the entire file into an in-memory array (or using mmap() to make it look like the file is in memory), you could then search for your character sequence in-memory, which is a bit easier to do:
// Works much like strstr(), except it looks for a binary sub-sequence rather than a string sub-sequence
const char * MemMem(const char * lookIn, int numLookInBytes, const char * lookFor, int numLookForBytes)
{
if (numLookForBytes == 0) return lookIn; // hmm, existential questions here
else if (numLookForBytes == numLookInBytes) return (memcmp(lookIn, lookFor, numLookInBytes) == 0) ? lookIn : NULL;
else if (numLookForBytes < numLookInBytes)
{
const char * startedAt = lookIn;
int matchCount = 0;
for (int i=0; i<numLookInBytes; i++)
{
if (lookIn[i] == lookFor[matchCount])
{
if (matchCount == 0) startedAt = &lookIn[i];
if (++matchCount == numLookForBytes) return startedAt;
}
else matchCount = 0;
}
}
return NULL;
}
.... then you can just call the above function on the in-memory data array:
char * ret = MemMem(theInMemoryArrayContainingFilesBytes, numBytesInFile, myShortSequence, 4);
if (ret != NULL) printf("Found it at offset %i\n", ret-theInMemoryArrayContainingFilesBytes);
else printf("It's not there.\n");
This program loads the entire file into memory and then uses std::search on it.
int main() {
std::string filedata;
{
std::ifstream fin("file.dat");
std::stringstream ss;
ss << fin.rdbuf();
filedata = ss.str();
}
std::string key = "\x39\xb5\x7d\xc6";
auto result = std::search(std::begin(filedata), std::end(filedata),
std::begin(key), std::end(key));
if (std::end(filedata) != result) {
std::cout << "found\n";
// result is an iterator pointing at '\x39'
}
}
const char delims[] = { 0x39, 0xb5, 0x7d, 0xc6 };
char buffer[4];
const size_t delim_size = 4;
const size_t last_index = delim_size - 1;
for ( size_t i = 0; i < last_index; ++i )
{
if ( ! ( is.get( buffer[i] ) ) )
return false; // stream to short
}
while ( is.get(buffer[last_index]) )
{
if ( memcmp( buffer, delims, delim_size ) == 0 )
break; // you are arrived
memmove( buffer, buffer + 1, last_index );
}
You are looking for 4 bytes:
unsigned int delim = 0xc67db539;
unsigned int uibuffer;
char * buffer = reinterpret_cast<char *>(&uibuffer);
for ( size_t i = 0; i < 3; ++i )
{
if ( ! ( is.get( buffer[i] ) ) )
return false; // stream to short
}
while ( is.get(buffer[3]) )
{
if ( uibuffer == delim )
break; // you are arrived
uibuffer >>= 8;
}
Because you said you cannot search the entire file because of null terminator characters in the string, here's an alternative for you, which reads the entire file in and uses recursion to find the first occurrence of a string inside of the whole file.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
string readFile (char *fileName) {
ifstream fi (fileName);
if (!fi)
cerr << "ERROR: Cannot open file" << endl;
else {
string str ((istreambuf_iterator<char>(fi)), istreambuf_iterator<char>());
return str;
}
return NULL;
}
bool findFirstOccurrenceOf_r (string haystack, char *needle, int haystack_pos, int needle_pos, int needle_len) {
if (needle_pos == needle_len)
return true;
if (haystack[haystack_pos] == needle[needle_pos])
return findFirstOccurrenceOf_r (haystack, needle, haystack_pos+1, needle_pos+1, needle_len);
return false;
}
int findFirstOccurrenceOf (string haystack, char *needle, int length) {
int pos = -1;
for (int i = 0; i < haystack.length() - length; i++) {
if (findFirstOccurrenceOf_r (haystack, needle, i, 0, length))
return i;
}
return pos;
}
int main () {
char str_to_find[4] = {0x39, 0xB5, 0x7D, 0xC6};
string contents = readFile ("input");
int pos = findFirstOccurrenceOf (contents, str_to_find, 4);
cout << pos << endl;
}
If the file is not too large, your best solution would be to load the whole file into memory, so you don't need to keep reading from the drive. If the file is too large to load in at once, you would want to load in chunks of the file at a time. But if you do load in chucks, make sure you check to edges of the chunks. It's possible that your chunk happens to split right in the middle of the string you're searching for.

c++ socket binary file

i have this function to get the content of file ,
#define BUFSIZE 512
vector<int> getContFile(char* pFile) {
ifstream vCin(pFile, ios::binary);
ifstream::pos_type size;
// get vLength of file:
vCin.seekg(0, ios::end);
size = vCin.tellg();
vCin.seekg(0, ios::beg);
vector<int> vTmp;
for (int i = 0; i < size; i++)
vTmp.push_back(vCin.get());
vCin.close();
return vTmp;
}
and this to send to the server
void SendFile() {
SendS("upFileUser");
int i;
vector<int> vTmp = getContFile("/usr/home/alex/Desktop/eval.tar");
for (i = 0; i < vTmp.size(); i += BUFSIZE) {
char *vBuff = new char[BUFSIZE];
for (int j = i; j < BUFSIZE; j++)
vBuff[j] = (char(vTmp[i]));
SendS(vBuff);
}
if (i < (vTmp.size() - 1)) {
char *vBuff = new char[vTmp.size() - i];
for (int j = 0; j < vTmp.size() - i; j++)
vBuff[j + i] = (char(vTmp[j + i]));
SendS(vBuff);
}
sendS("endOfFileTransmision");
}
void SendS(char* pSir) {
int vLen = strlen(pSir);
write(pSocket, &vLen, sizeof (int));
write(pSocket, pSir, vLen);
}
this is the receve function
char* reciveS() {
char* vTmp;
int vCt = 0;
read(pSocket, &vCt, sizeof (vCt));
if (vCt != 0) {
vTmp = new char[vCt];
read(vSocket, vTmp, vCt);
} else {
vTmp = NULL;
}
return vTmp;
}
bool receveFile(void) {
char* vReceve = reciveS();
if (strcmp(vReceve, "upFileUser") == 0)
{
ofstream vCoutFile;
vCoutFile.open("data2.tar", ios::out | ios::binary);
while (true) {
char *vTmp = new char[BUFSIZ];
vTmp = reciveS();
cout<<vTmp;
if (strcmp(vTmp, "endOfFileTransmision") == 0) break;
else {
cout << vTmp;
vCoutFile << vTmp;
}
}
vCoutFile.close();
}
}
and the result are a broke pipe(i run this to freebsd 6.4 amd with g++ compiler) , so what i miss , the connection are good i can transfer text from client to server and reverse the problem are with binary file
I see two problems with your code:
You are making a lot of allocations (new) but you never free the memory.
In the SendS function you are taking the string length, but the data in that "string" is from a vector of integers and is binary. This means that the data can contain the string-terminating '\0' character (the integer 0).
Besides that, I really don't follow what you are doing. Instead of reading into a vector, create a char-buffer and allocate enough memory to put the whole file into that buffer (char *buffer = new char[length_of_file]) and send it, with the length of the buffer first.
Something like this:
std::pair<size_t, char *> getContFile(const char *pFile)
{
ifstream vCin(pFile, ios::binary);
ifstream::pos_type size;
vCin.seekg(0, ios::end);
size = vCin.tellg();
vCin.seekg(0, ios::beg);
char *buffer = new char[size];
vCin.read(buffer, size);
return std::make_pair(static_cast<size_t>(size), buffer);
}
void SendFile()
{
SendS("upFileUser", strlen("upFileUser"));
std::pair<size_t, char *> vTmp = getContFile("/usr/home/alex/Desktop/eval.tar");
SendS(vTmp.second, vTmp.first);
delete [] vTmp.second;
}
void SendS(char *buffer, size_t length)
{
// Send the length
size_t tmp = htonl(length);
write(pSocket, &tmp, sizeof(tmp));
// Send the buffer
while (length > 0)
{
ssize_t sent = write(pSocket, buffer, length);
if (sent <= 0)
{
// Some kind of error
break;
}
buffer += sent;
length -= sent;
}
}
Do something similar on the receiving side.