I have records coming in from fgets (web data using popen(), not a file) that are in const char * array format.
const char * cstr = buff;
The 3rd item is a string and needs to either be removed or changed to a zero.
How do I access the 3rd element in a const char * array stream in increments of 5?
1
2
string
4
5
1
2
string
4
5
code:
while(fgets(buff, sizeof buff, fp) != NULL)
{
const char * cstr2 = buff;
for(int i = 0; i < 5; ++i){
if(i == 3){
if (!strcmp(cstr2, "Buy\n")) {
printf("Found One!\n");
cstr2[2] = 0;
}
if (!strcmp(cstr2, "Sell\n")) {
printf("Found Two!\n");
cstr2[2] = 0;
}
}
}
}
expected output:
1
2
0
4
5
1
2
0
4
5
error:
no match and :
error: assignment of read-only location '*(cstr2 + 2u)'
How do you correctly access the 3rd element in a char streaming char array?
This solution was previously posted by anonymous:
char* getmyData()
{
char buff[BUFSIZ];
FILE *fp = popen("php getMyorders.php 155", "r");
if (fp == NULL) perror ("Error opening file");
size_t size = 1000;
char* data = (char*)malloc(size);
char* ptr = data;
std::string::size_type sz;
int i=0;
while(fgets(buff, sizeof(buff), fp) != NULL)
{
const char * cstr2 = buff;
const char* test = ptr;
//for(int i = 0; i < 5; ++i)
{
if(i == 2){
if (!strcmp(cstr2, "Buy\n")) {
printf("Found One!\n");
strcpy(ptr,"0\n");
//ptr+=2;
}
else
if (!strcmp(cstr2, "Sell\n")) {
printf("Found Two!\n");
strcpy(ptr,"0\n");
//ptr+=2;
}
else
{
strcpy(ptr,cstr2);
ptr+=strlen(cstr2);
}
}
else
{
strcpy(ptr,cstr2);
ptr+=strlen(cstr2);
}
try
{
int nc = std::stod (test,&sz);
std::cout << "Test: " << 1+nc << "\n";
}
catch(...)
{
}
i++;
if (i==5)
i=0;
}
if (ptr-data+100>=size)
{
int ofs = ptr-data;
size*=2;
data = (char*)realloc(data,size);
ptr = data+ofs;
}
}
return data; // DONT FORGET TO call free() on it
}
From your sample code it is not clear what is the expected output. Is it an array of integer ? a formatted text string ? a byte array ? we can't know.
Assuming you have a text formatted input and want a text formatted output, a simple solution is to write a new string with the correct values and not try to modify your input buffer.
If you know the exact format of your input records you could use fscanf to do the parsing instead of doing it by hand. And you could use ssprintf to do the formatting of the output string.
As others pointed out, if you can use C++, you'd have safer/easier options. Please comment about your willingness to use C++.
Related
sorry for such a stupid question but I couldn't find any obvious answer.
I need to read from stdin first an int n with the size of an array, and then integer values from a string in the format "1 2 3 4 5 6" with n elements.
If I knew the number of parameters at compile time I could use something like a scanf (or the safe alternatives) with a format string like "%d %d %d %d %d %d", but here I will only know that value at run time.
What would be the best way to do this in C++? Performance is important but more than that safety.
How should I read a format string of variable length in C++ from stdin?
You should not attempt to do such thing. Only ever use constant format strings.
I need to read from stdin first an int n with the size of an array, and then integer values
What would be the best way to do this in C++?
Read one value at a time. Repeat using a loop.
Here's a function that does what errorika describes:
const int SIZE = //as much of your memory as you'd like the user to have access to
***caller function must include this:
//allocate a string to hold some data;
char* buffer = NULL;
buffer = malloc (SIZE * sizeof(char));
if (buffer == NULL) {
printf("malloc error terminating\n");
return;
}
***
void getEntry(char* buffer) {
int count = 0;
int maxlen = SIZE - 1;
char a = '0';
for (int i = 0; i < SIZE; i++) {
buffer[i] = '0';
}
while (a != '\n' && count < maxlen) {
a = fgetc(stdin);
buffer[count] = a;
count++;
}
if (a == '\n') {
buffer[count - 1] = '\0';
}
else {
buffer[count] = '\0';
do {
a = fgetc(stdin);
} while (a != '\n');
}
}
This is all basic C code but user entry is evil. Here is what I've come up with for more C++ idiomatic user input functions (query is just the message string you pass in):
template<typename T>
void getInput(const std::string query, T& entry) {
std::string input;
std::cout << query << std::endl;
getline(std::cin, input);
std::stringstream buffer{input};
buffer >> entry;
}
OR
template<typename T>
void getInput2(std::string query, T& entry) {
bool validInput = false;
while (validInput == false)
{
validInput = true;
std::cout << query << std::endl;
std::cin >> entry;
if (std::cin.fail()) {
validInput = false;
std::cout << "Unacceptable entry\n" << std::endl;
}
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
I am trying to write my own operating system. I have followed the tutorials on the OSDev Wiki, and I am now working on writing a console mode, with commands. I need to be able to split a char* into a char**, without all the library functionality (hence freestanding). I have tried iterating through until I meet my delimiter etc, but however I do it, I just get garbage stuck on the end of my first result. What am I doing wrong? This is what I have so far:
static char** splitStr (char* string, char delim) {
char returner[VGA_WIDTH][255];
int loc = 0;
int innerLoc = 0;
for (int i = 0; string[i] != 0x00; i++) {
char c = string[i];
if (c != delim) {
returner[loc][innerLoc] = c;
innerLoc++;
} else {
print ("a string was ");
println (returner[loc]);
innerLoc = 0;
loc++;
}
}
print ("the first string was ");
println (returner[0]);
return (char**)returner;
}
I am asking a question about how to write a specific function in C++ freestanding mode.
void split(const char* str, const char d, char** into)
{
if(str != NULL && into != NULL)
{
int n = 0;
int c = 0;
for(int i = 0; str[c] != '\0'; i++,c++)
{
into[n][i] = str[c];
if(str[c] == d)
{
into[n][i] = '\0';
i = -1;
++n;
}
}
}
}
I'm allocating using calloc to get rid of garbage characters.
EDIT: You should allocate the pointers inside the char** before writing to them.
void allocarr(char** pointers, int bytes, int slots)
{
int i = 0;
while(i <= slots)
{
pointers[i] = (char*)calloc(1, bytes);
++i;
}
}
...
char** sa = (char**)malloc(50*sizeof(char*));
allocarr(sa, 512, 50);
split("Hello;World;", ';', sa);
puts(sa[0]);
I have a program, that asks several strings and should sort them.
My code is:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 256
int myStrCmp (const void * a, const void * b)
{
return strcmp((const char *)a, (const char *)b);
}
int main(void)
{
int strNum; // expected number of input strings
int strCnt; // counter of strings
char ** storage; // pointr to the memory when strings are stored
char strBuf[ MAX_STR_LEN]; // buffer for strings
char * strPtr;
// input of strings number
do{
printf("How many strings will be entered: ");
while( scanf("%d", &strNum) != 1)
{
printf("ERROR: Not number was entered!\n");
while( getchar() != '\n' );
printf("Please enter a number: ");
}
if( strNum < 2 )
{
printf("ERROR: Number less than 2 was entered!\n");
}
while( getchar() != '\n' );
}
while(strNum < 2);
// allocation of memory for pointers
storage = (char **) calloc(strNum, sizeof(char*) );
if( storage == NULL )
{
printf("ERROR: Unexpected problems with memory allocation!\n");
return 1;
}
// input of strings
for( strCnt = 0; strCnt < strNum; strCnt++)
{
printf("Enter string #%d:\n", strCnt + 1);
fgets(strBuf, MAX_STR_LEN, stdin);
strPtr = strchr(strBuf, '\n');
if( strPtr )
{
*strPtr = '\0';
}
else
{
strBuf[ MAX_STR_LEN - 1] = '\0';
}
// allocation memory for particular string
storage[strCnt] = (char *) malloc(strlen(strBuf) + 1);
if(storage[strCnt] == NULL)
{
printf("ERROR: Unexpected problems with memory allocation!\n");
return 2;
}
// move string to dynamic memory
strcpy(storage[strCnt], strBuf);
}
// sort the strings
qsort(storage, strNum, sizeof(char**), myStrCmp);
// output the result
printf("\nSorted strings:\n");
for( strCnt = 0; strCnt < strNum; strCnt++)
{
printf("%s\n", storage[strCnt]);
}
return 0;
}
The simplest test shows the trouble:
How many strings will be entered: 3
Enter string #1:
ddd
Enter string #2:
aaa
Enter string #3:
ccc
Sorted strings:
ddd
aaa
ccc
I have tryed Visual C++ and gcc, but the result is the same. Please, say me what is wrong in the code?
The problem is in myStrCmp function.
Because a and b are elements in not a simple array, but in array of pointers, their type must be char ** and function that compares two elements have to be as follows:
int myStrCmp (const void * a, const void * b)
{
return strcmp(*(const char **)a, *(const char **)b);
}
I am having the following problem with my code, though it compiles correctly:
value type const char cannot be used to initialize an entity of type char*
Can someone help me? I can run the code which is weird but I can't create a makefile using this. It's very weird to me.
int SpliString(struct dict_word *entry, const char *str)
{
long word_length,j,k;
int yearIndex;
char *buffer;
char *endOfYears;
char *endOfYear;
char *endOfDefinition;
char *endOfWord = strstr(str, "_#_");
//Sets the first num bytes of the block of memory pointed by ptr
//to the specified value (related as an unsigned char)
memset(entry, 0, sizeof(struct dict_word));
// If '_#_' is not found, it's NULL
if (endOfWord)
{
// Calculating word legth; 'str' points to start of word, 'endofWord' points to '_#_' that is just after word
word_length = endOfWord - str;
// Copying data into the word
strncpy(entry->words, str, word_length);
// 'endOfYears' points to '_#_,' but wee need to find follow '_#_'
// therefore there is added 3 in order to skip curremnt '_#_
endOfYears = strstr(endOfWord+3, "_#_");
if (endOfYears)
{
word_length = endOfYears - (endOfWord+3);
// Skips _#_
buffer = endOfWord+3;
yearIndex = 0;
j = 0;
// Finds next year in the line, it stops if all 10 years is filled
// or end of years string is reached
while(yearIndex<10 && buffer+j<endOfYears)
{
// Stores year in the buffer, with converting 'stirng' to 'int'
entry->year[yearIndex] = atoi(buffer+j);
// check year for negative...
if (entry->year[yearIndex]<=0)
return 0;
// Locating substring; 'j' is current offset from beginning of buffer
endOfYear = strchr(buffer+j, '_');
if (endOfYear)
{
j = endOfYear - buffer;
j++;
yearIndex++;
}
else
{
break;
}
}
//endOfYears points to '_#_' that separatates 'years' and 'definition'
//and there is needed to find '_#_' between 'definition' and 'synonyms'
//therefore it skips '_#_' that separatates 'years' and 'definition',
//+3, because '_#_' has length = 3
endOfDefinition = strstr(endOfYears+3, "_#_");
if (endOfDefinition)
{
word_length = endOfDefinition - (endOfYears+3);
k = 0;
for(j=0; j<word_length; j++)
{
// Skips '_#_'
if (endOfYears[j+3]==',')
{
entry->eng_synonyms[k] = ' ';
k++;
}
else if (endOfYears[j+3]>='a' && endOfYears[j+3]<='z')
{
entry->eng_synonyms[k] = endOfYears[j+3];
k++;
}
else if (endOfYears[j+3]!='_')
{
return 0;
}
}
k = 0;
word_length = (str+strlen(str)) - (endOfDefinition+3);
for(j=0; j<word_length; j++)
{
if (endOfDefinition[j+3]==',')
{
entry->heb_synonyms[k] = ' ';
k++;
}
else if (endOfDefinition[j+3]>='A' && endOfDefinition[j+3]<='Z')
{
entry->heb_synonyms[k] = endOfDefinition[j+3];
k++;
}
else if (endOfDefinition[j+3]!='_')
{
return 0;
}
}
}
// Check for legality
// Check all symbols of 'entry->words'
// calculate length and supress warning
for(j=0;j<(int)strlen(entry->words);j++)
{
if (entry->words[j]<'a' || entry->words[j]>'z')
return 0;
}
return 1;
}
}
return 0;
}
Use
const char *buffer;
const char *endOfWord = strstr(str, "_#_");
Confident OP is compiling in C++.
// C
char *strstr(const char *s1, const char *s2);
// C++
const char* strstr(const char* s1, const char* s2);
char* strstr( char* s1, const char* s2);
See
Compile C app with Visual Studio 2012
How to compile and execute C program on Visual Studio 2012 for Windows 8?
I am writing a binary I/O for storing data in my application.
For illustration consider I want to store a double array of size 10 to the file.
Now since it is not guaranteed that double uses 8 bytes on all platforms, the reader of the file needs to be be modified a bit.
Although I am using Qt I think the problem is mainly in the way data read in char * is translated into double. The data read is almost zero.
For example, 1 is read as 2.08607954259741e-317.
Why is every double being read as zero even thought it is not?
void FileString::SaveBinary()
{
QFile *file = new QFile(fileName);
if (!file->open(QFile::WriteOnly))
{
QString err = file->errorString();
QString *msgText = new QString("Could not open the file from disk!\n");
msgText->append(err);
QString *msgTitle = new QString("ERROR: Could not open the file!");
emit errMsg(msgTitle, msgText, "WARNING");
delete file;
return;
}
QDataStream out(file);
QString line = "MyApp";
out << line;
line.setNum(size);//size = 10
out << line;
line.setNum(sizeof(double));
out << line;
for(int i = 0; i < size; i++)
{
out << array[i];
}
if(out.status() != QDataStream::Ok)
{
qCritical("error: " + QString::number(out.status()).toAscii());
}
file->close();
delete file;
}
void FileString::ReadBinary()
{
bool ok = false;
QString line = "";
QFile *file = new QFile(fileName);
if (!file->open(QFile::ReadOnly))
{
QString err = file->errorString();
QString *msgText = new QString("Could not open the file from disk!\n");
msgText->append(err);
QString *msgTitle = new QString("ERROR: Could not open the file!");
emit errMsg(msgTitle, msgText, "WARNING");
delete file;
return;
}
QDataStream in(file);
in >> line;
if(line.simplified().contains("MyApp"))
{
in >> line;
size = line.simplified().toInt();
if(size == 10)
{
int mysize = 0;
in >> line;
mysize = line.simplified().toInt();
if(1)//this block runs perfect
{
for(int i = 0; i < size; i++)
{
in >> array[i];
}
if(in.status() == QDataStream::Ok)
ok = true;
}
}
else if(1)//this block reads only zeros
{
char *reader = new char[mysize + 1];
int read = 0;
double *dptr = NULL;
for(int i = 0; i < size; i++)
{
read = in.readRawData(reader, mysize);
if(read != mysize)
{
break;
}
dptr = reinterpret_cast<double *>(reader);//garbage data stored in dptr, why?
if(dptr)
{
array[i] = *dptr;
dptr = NULL;
}
else
{
break;
}
}
if(in.status() == QDataStream::Ok)
ok = true;
delete[] reader;
}
}
}
if(!ok || (in.status() != QDataStream::Ok))
{
qCritical("error : true" + " status = " + QString::number((int) in.status()).toAscii());
}
file->close();
delete file;
}
EDIT:
Contents of the generated file
& M y A p p 1 . 1 8 . 3 . 0 1 0 8?Ă° # # # # # # # #" #$
That is supposed to contain:
MyApp 1.18.3.010812345678910
"MyApp 1.18.3.0" "10" "8" "12345678910"
What do you expect to read if sizeof double on read platform differs from sizeof double on write platform?
Suppose sizeof double on your write platform was 10. Then you stored a sequence of 10 bytes in a file that represents a 10-byte double. Then, if sizeof double on your read platform is 8, you would try to parse bits of an 10-byte double into an 8-byte and that would obviously end up with garbage.
Here's a more intuitive example with ints:
If you a have a 2-byte integer number, say 5. If you store it in binary file, you'll get a sequence of 2 bytes: 00000000 00000101. Then, if you try to read the same number as a 1-byte int, you'll manage to read only the first byte, which is 00000000 and get just zero as a result.
Consider using strings to save doubles for portability https://stackoverflow.com/a/6790009/817441
Note that in your original code sizeof(double) could work instead of the hard-coded string, but it will not as long as to migrate to a different architecture with a different double size on it.
As a side note if you are worried about the performance of the double to string conversion, you may have more problems when your users or you would like to move to embedded later. I have just run some conversions in a loop, and it is not that bad on my old laptop either. Here is my very poor benchmark result:
time ./main
real 0m1.244s
user 0m1.240s
sys 0m0.000s
I would like to point it out again that it is an old laptop.
for the code:
#include <QString>
int main()
{
for (int i = 0; i < 1000000; ++i)
QString::number(5.123456789012345, 'g', 15);
return 0;
}
So, instead of the non-portable direct write, I would suggest to use the following method:
QString QString::number(double n, char format = 'g', int precision = 6) [static]
Returns a string equivalent of the number n, formatted according to the specified format and precision. See Argument Formats for details.
Unlike QLocale::toString(), this function does not honor the user's locale settings.
http://doc-snapshot.qt-project.org/qdoc/qstring.html#number-2
Having discussed all this theretically, I would be writing something like this if I were you:
void FileString::SaveBinary()
{
QFile *file = new QFile(fileName);
if (!file->open(QFile::WriteOnly))
{
QString err = file->errorString();
QString *msgText = new QString("Could not open the file from disk!\n");
msgText->append(err);
QString *msgTitle = new QString("ERROR: Could not open the file!");
emit errMsg(msgTitle, msgText, "WARNING");
delete file;
return;
}
QDataStream out(file);
QString line = QString::number(myDouble);
out << line;
for(int i = 0; i < size; i++)
{
out << array[i];
}
if(out.status() != QDataStream::Ok)
{
qCritical("error: " + QString::number(out.status()).toAscii());
}
file->close();
delete file;
}
One portable option could be to use long double, but of course that would increase the computation at other places, so depending on the scenario, it may or may not be an option.