I have a char buffer which contains characters read from a file. I need to take this char buffer and find the first end of line character within it.
EOL characters in this case are \n,\r,\f.
Initially, I was planning to do the following:
// let's read into our buffer now...
char * m_pLineBuff;
if(!readCharBuf(m_pLineBuff, bytesToRead)) { report("Could not fill line buffer", RPT_ERROR, __PRETTY_FUNCTION__); }
// setup our newline candidates in an array
int iEOLChars[] = {'\n','\f','\r'};
// find the first instance of a newline character
int iEOLPosition = std::find_first_of(m_pLineBuff, m_pLineBuff+bytesToRead, iEOLChars, iEOLChars+3);
However, I apparently cannot pass a char pointer to the std::find_first_of method -- I can only pass an integer. The exact error the compiler provides me is:
error: invalid conversion from ‘char*’ to ‘int’
This seems strange to me, as I've defined the start and end locations of my char buffer and I do not understand why it could not iterate through them looking for the first occurrence of any of my EOL characters.
Any advice on how to resolve this? Is there a way to use find_first_of, or should I simply iterate through each position of the char buffer and check to see if the char at the location matches any of my EOL characters.
The "find_first_of" function I am referring to is this one: http://www.cplusplus.com/reference/algorithm/find_first_of/
Any assistance is always appreciated.
The function find_first_of returns, in this case, a pointer, not an index, so try:
char *iEOLPosition = std::find_first_of(m_pLineBuff, m_pLineBuff+bytesToRead, iEOLChars, iEOLChars+3);
I think the problem is a type mismatch here:
char * m_pLineBuff;
int iEOLChars[] = {'\n','\f','\r'};
Try it declaring your iEOLChars as a char array.
Check your first_first_of function I think it can never have 4 parameters
Refer first_first_of
Related
I am scanning strings as input , i am using getline to do so e.g
char *lajna=NULL;
size_t dlzka=0;
getline(&lajna,&dlzka,stdin);
and i want to read first char using fgetc , i tried to do
test=fgetc(lajna);
but it throws error
cannot convert ‘char**’ to ‘FILE* {aka _IO_FILE*}’ for argument ‘1’ to
‘int fgetc(FILE*)’
ciarka=fgetc(&lajna);
i checked it up and found nothing how to read chars from buffer like this, what is the right way?
See the prototype of fgetc():
int fgetc(FILE *stream);
It takes a FILE* as argument but you are passing char*. Hence, the error. (The error message suggests you actually have it like: test=fgetc(&lajna);)
To read characters from lajna, you don't need to use any function or special mechanism. You can simply index into it:
char ch = lajna[0]; // first char
and so on.
Or you can use a loop to read all chars.
for(i=0; lajna[i]; i++) { //until the null terminator '\0'
char ch = lajna[i];
}
I'm trying to pass in a memory reference to a character in a string and edit it in a function using C. The code is below:
void EditChar(char *input) {
printf("# %s #",*input);
*input = *input << 1
}
int main() {
char *string ="aaaa";
EditChar(&string[2]);
printf("%s",string);
}
I can print the character inside the function fine which I presume must mean it's following the pointer so why am I unable to edit the pointer location of that character, any ideas?
The lack of a ; on line 3 is going to cause problems to start with.
You're passing a character instead of a character pointer on line 2.
And on my mac, once you fix those problems, you get a bus error on line 3 because you're trying to change read-only memory.
char *string =strdup("aaaa");
and now it works.
Also, as stated in question comments, instead of strdup, you may want to use
char string[] = "aaaa";
I'm getting the following error with memcpy. It doesn't give compilation error but doesn't give the result I would imagine. I've never used memcpy before so I'm sure I'm making a simple mistake. I've looked around previous questions but couldn't find one with structures. I can use memcpy on independent variables but just not on structs.
If someone can point out my mistake it'll be great.
#include <stdio.h>
#include <string.h>
int main() {
struct st{
char c1[12];
char c2[32];
char c3[3];
char c4[7];
char c5[13];
char c6[5];
char c7[10];
};
struct st s;
char s1[] = "part number";
char s2[] = "j9uijd9d09fj";
char s3[] = "abc";
char s4[] = "seven";
char s5[] = "aaaaaaaa";
char s6[] = "ptype";
char s7[] = "user";
memcpy(s.c1,s1,sizeof(s.c1));
memcpy(s.c2,s2,sizeof(s.c2));
memcpy(s.c3,s3,sizeof(s.c3));
memcpy(s.c4,s4,sizeof(s.c4));
memcpy(s.c5,s5,sizeof(s.c5));
memcpy(s.c6,s6,sizeof(s.c6));
memcpy(s.c7,s7,sizeof(s.c7));
printf("%s\n",s.c1);
printf("%s\n",s.c2);
printf("%s\n",s.c3);
printf("%s\n",s.c4);
printf("%s\n",s.c5);
printf("%s\n",s.c6);
printf("%s\n",s.c7);
return 0;
}
OUTPUT I'm getting :
part number
j9uijd9d09fj
abcseven
seven
aaaaaaaa
ptypeuser
user
Thanks!!!
Change the size of c3 in your struct to 4 and c6 to 6 to allow for the NULL terminator.
struct st{
char c1[12];
char c2[32];
char c3[4]; /* putting 'abc' which is 4 chars */
char c4[7];
char c5[13];
char c6[6]; /* putting 'ptype' which is 6 chars */
char c7[10];
};
printf with %s prints a null-terminated string. s3 (and s6) in this case has the null-terminating character overwritten by c so printf stops printing it when it reaches the next one, which is after seven.
Your code is wrong for two things:
s.c3 is 3 characters in length, so there is no room for the extra NUL byte. That's why you get it concatenated with the next one on printing.
In some cases, you are copying more bytes than there is in the original string: memcpy(s.c2,s2,sizeof(s.c2)) is copying 32 bytes, but the original string is far shorter. That is undefined behaviour.
Probabl you want to use strcpy().
Or even strncpy, but beware! this functions does not do what most people think... Read the documentation at least twice before using it.
In the structure the member c3 is an array of three characters. You then copy four characters into it! Remember that strings have an extra character that ends the string, so the string "abc" is actually four characters: 'a', 'b', 'c' and the terminator '\0'.
The same for the c6 member of the structure.
The problem you are facing is the missing NUL-terminator of the character sequences.
A character sequence as you constructor them, is always one character longer then the amount of characters you types in. The additional character at the end is the NUL-terminator.
So the arrays you copy your thing in, need to be one character longer then the amount of characters you want to copy in. For c3 the amount of characters is too small, causing the NUL-terminator to be missing.
printf then prints your string character by character until it sees the NUL-terminator. In case its missing, printf just continues reading the memory until it hits the first 0x00-byte. In this case you are lucky because you are using a structure. Structures are written in one block of memory so printf just drops into the next field.
You solve your problem simply by ensuring that the arrays sizes in the structure are always larger then the character sequences you want to copy in.
So I'm not very good with C but I'm designing a GLUT application that reads in a file that is not case sensitive. To make it easier I want to convert my strings to all lower case. I made a function makeLower that is modifying a variable that was passed in by reference.
I have a While Loop in the method makeLower that seems to get through part of the first iteration of the while loop and then the EXE crashes. Any tips would be great, thanks!
Output:
C:\Users\Mark\Documents\Visual Studio 2010\Projects\Project 1\Debug>"Project 1.e
xe" ez.txt
Line is #draw a diamond ring
Character is #
Then error "project 1.exe has stopped working"
Code:
void makeLower(char *input[]){
int i = 0;
printf("Line is %s\n", *input);
while(input[i] != "\0"){
printf("Character is %c\n", *input[i]);
if(*input[i] >= 'A' && *input[i] <= 'Z'){
*input[i] = tolower(*input[i]);
}
i++;
}
}
int main(int argc, char *argv[]) {
FILE *file = fopen(argv[1], "r");
char linebyline [50], *lineStr = linebyline;
char test;
glutInit(&argc, argv);
while(!feof(file) && file != NULL){
fgets(lineStr , 100, file);
makeLower(&lineStr);
printf("%s",lineStr);
//directFile();
}
fclose(file);
glutMainLoop();
}
I see more problems now, so I extend my comments to an answer:
You allocate an array of 50 characters, but tell fgets to get up to 100 characters, which might be fatal as fgets will overwrite memory not in the string.
When passing a C string to a function, you don't have to pass the address of the pointer to the string (&lineStr), the actual pointer or array is okay. This means you can change the makeLower function to void makeLower(char *input) or void makeLower(char input[]). Right now the argument to makeLower is declared as an array or char pointers, not a pointer to an array of char.
In the new makeLower I proposed above, you can access single characters either as an array (input[i]) or as a pointer plus offset (*(input + i). Like I said in my comment, the last version is what the compiler will probably create if you use the first. But the first is more readable so I suggest that.
Also in makeLower you make a comparison with "\0", which is a string and not a character. This is almost right actually: You should use input[i] != '\0'.
And finally this is how I would implement it:
void makeLower(char *input)
{
while (*input != '\0') /* "while (*input)" would also work */
{
*input = tolower(*input);
input++;
}
}
A few explanations about the function:
All char arrays can be converted to a char pointer, but not the other way around. Passing char pointer is the most common way to pass a string actually, as you can see from all standard functions that accepts strings (like strlen or strcpy.)
The expression *input dereferences (i.e. takes the value of what a pointer points to) the string. It is the same as *(input + 0) and so get the value of the first character in the string.
While the first character in the string is not '\0' (which technically is a normal zero) we will loop.
Get the first character of the string and pass it to the tolower function. This will work no matter what the character is, tolower will only turn upper case characters to lower case, all other characters will be returned as they already were.
The result of tolower copied over the first character. This works because the right hand side of an assignment must be executed before the assignment, so there will not be any error or problem.
Last we increase the pointer by one. This will make input point to the next character in the string. This works because input is a local variable, so operations on the pointer will not affect anything in the calling function.
This function can now be called like this:
char input[100];
fgets(input, sizeof(input), stdin);
printf("before: \"%s\"\n", input);
makeLower(input);
printf("after : \"%s\"\n", input);
Did you try while(*input[i] != "\0") instead of what you have ? For some reason you seem to pass to your function a pointer to pointer to char (*input[]) and &lineStr so it would make sense to dereference twice when you check for string terminator character "\0"....
Just a thought, hope it helps
I think the problem is that you don't know that the string is going to equal '\0' when you want it to. So you may be going out of bounds which is very likely that you don't know the length of the string.
As far as I understand things, it's fine to pass '\0' to tolower(). It's a valid unsigned char value, and tolower() simply returns the input character if it is not able to do any conversion.
Thus, the loop can be succinctly put as:
while(input[i] = tolower(input[i]))
++i;
This does one more call to tolower(), but it's shorter and (imo) quite clear. Just wanted to mention it as an alternative.
I am trying to copy certain parts of a string into other, new strings, but when i try to do it and print the results it gives me weird output.. I really hope someone can help. I have a feeling that it is something about missing pointers.. Here is my source;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void getData(char code[], char ware[], char prod[], char qual[])
{
printf("Bar code: %s\n", code);
/* Copy warehouse name from barcode */
strncpy(ware, &code[0], 3);
ware[4] = "\0";
strncpy(prod, &code[3], 4);
prod[5] = "\0";
strncpy(qual, &code[7], 3);
qual[4] = "\0";
}
int main(){
/* allocate and initialize strings */
char barcode[] = "ATL1203S14";
char warehouse[4];
char product[5];
char qualifier[4];
getData(&barcode, &warehouse, &product, &qualifier);
/* print it */
printf("Warehouse: %s\nID: %s\nQualifier: %s", warehouse, product, qualifier);
return 0;
}
EDIT:
The wierd output is:
Bar code: ATL1203S14
Warehouse: ATL
ID: ♫203(♫>
Qualifier: S14u♫203(♫>
I think you meant '\0' instead of "\0" and 3 instead of 4:
ware[4] = "\0";
Try:
ware[3] = 0;
Also the & in getData(&barcode, &warehouse...) are useless. Just use getData(barcode, warehouse...);.
You're writing past the end of the chars in your getData() function. You've defined char product[5], which allocates 5 bytes of memory. That gives you array indexes 0,1,2,3,4. In getData, you write the product's null terminator to index 5, which is past the end of product, and will overwrite the next var's first character.
The same applies for barecode, warehouse, and qualifier.
Arrays in C and C++ are zero-based. The last index is one less than the length. You're setting a value in the memory after the array, for each of the arrays ware, prod and qual.
For example, instead of
char warehouse[4];
ware[4] = "\0";
you'd want:
char warehouse[4];
ware[3] = "\0";
getData(&barcode, &warehouse, &product, &qualifier);
This is not the way you should call getData. getData takes pointers, arrays are automatically converted to pointers, so theres no need to use the address-of operator &.
You should use
getData(barcode, warehouse, product, qualifier);
The sizes of the strings inside main() don't include a place for the sentinel.
You need to have:
char warehouse[5];
char product[6];
char qualifier[5];
Also, You are assigning a pointer to the string "\0" into a character, where you should be assigning the character '\0' itself.
I think I'd do things a bit differently. In particular, strncpy is almost never really useful (I'm reasonably certain it was invented for file names in the original Unix FS, and while it fits their specific requirements quite nicely, those requirements are sufficiently unusual that it's rarely good for much of anything else).
Instead, I'd use sscanf: sscanf(code, "%4c%5c%4c", ware, prod, qual);
Your question does not make it clear whether this is really correct. As others have pointed out, you're writing past the ends of the space you've allocated. Above, I've assumed you specified the number of characters you want to copy, so you'd have to expand each of the allocations by one character to make room for the terminator. Alternative, if you've already left room for the terminator and want one fewer character copied, you'd have to reduce each of the lengths above by one so the format string would be "%3c%4c%3c".