Ending char* vector in c - c

How do I mark the end of a char* vector with '\0' to null-terminate it?
If i have char* vector:
char* param[5];
I thought of either
param[4] = '\0';
or
char c = '\0';
param[4] = &c;
but none of them seem to work?
param is a char-pointer vector, supposed to point to 5 strings(char-vectors).

Ok you are trying to end a vector of strings, something similar to what is passed to main as argv. In that case you just need to assign a null pointer:
param[4] = 0;

If you really have an array of char*, you can do:
param[4] = "";
(Your second approach actually should work as long as you don't need param[4] to be valid when c goes out of scope.)
A better sentinel value usually would be the null pointer, however:
param[4] = NULL;

A char* vector is a vector of pointer to chars. You probably want a vector of char. In that case, you could write:
char vect[5] = { '\0' };
In this way the vector is initialized with all '\0' characters.
If you really want an array of char pointer you can do similarly:
char* vect[5] = { NULL };
All pointers to string will be initialized with NULL.

I would probably write something like below:
#include <stdio.h>
int main(){
char* param[5] = {"1", "2", "3", "4", NULL};
int i = 0;
for (i = 0; param[i] ; i++){
printf("%s\n", param[i]);
}
}
Instead of NULL I could use 0, or '\0' as all are the same in the end (numerical value 0), but I believe using the NULL macro capture best the intention.
You can also write param[4] = NULL; if it's done after the initialization, and you param[4] = '\0'; should have worked (but looks more like obfuscation as you don't want a char at all, but a NULL pointer)

Your
char* param[5];
vector cannot be 'null terminated' - it is a vector of char pointers. You can only null terminate arrays of chars (by putting a '\0' whereever you want to terminate the char array.
Hence, I guess the correct answer to your question would be mu: Your question cannot be answered because it's based on incorrect assumptions. :-)

Related

comparing string to words in an array

I got an assignment from my teacher to write a code that compares a given word to a bunch of words located in an array of strings.
If the word in the array is lexicography smaller than the word given, I need to put it inside a new array.
else, I'm moving to the next word.
for example;
given word: hello
arr=bus, alpha, world, java.
new array=bus,alpha.
I wrote a code that does that using STRCMP, but the computer throws me out when it gets to the strcpy part.
this is my code
char** LowerSTR(char* arr[], int size_arr, char* str, int* size_res)
size_res = 0;
char** newArr= (char**)calloc(size_arr, sizeof(char));
for (int i = 0; i < size_arr; i++)
{
if (strcmp(str, arr[i])==1)
{
for (int k = 0; k <size_arr;k++)
{
strcpy(newArr[k], arr[i]);
}
size_res++;
}
}
if (size_res == 0)
return NULL;
else return newArr;}
maybe I should use STRCAT instead?
please help :\
In calling strcpy with newArr[k] as an argument you're dereferencing a NULL pointer.
Recall that we allocate newArr as follows:
char** newArr= (char**)calloc(size_arr, sizeof(char));
There's actually multiple errors here. The first is that we calloc with sizeof(char) when we in fact want a region of char*s. So corrected1
we have
char** newArr= calloc(size_arr, sizeof(char*));
As we've calloc'd this piece of memory, all of it is zeroed. Thus when strcpy internally accesses newArr[k] (itself of type char*) it points to memory address 0, which is likely reversed by the OS, and in any case, not a valid address in the context of our program.
In order to resolve this, we need to allocate for each string. For instance, one might do
newArr[k] = malloc(strlen(arr[i]) + 1); // The +1 is for the \0 termination character
the line before we strcpy.
You also have a bug with size_res as you just treat it as an int instead of an int* as you need to dereference it when you want to change or read the value to which it points.
1 See here for why I've removed the cast.
You should scan newArr and print all strings inside, something like:
for (int i = 0; i < *size_res; i++) // !
{
printf("%s\n",newArr[i]);
}
(!) 'size_res' is passed to the function as a pointer to int,

How do I receive a char array in a C function?

I wish to split a "string" by the character ','.
The string holds a GPS NMEA encoded string, but that is of no matter.
My problem is that sometimes the parameter from the function that processes this char array is empty... Like nothing is in the array.
How should I correctly pass a "char string[]" to a function so that I may operate on a that parameter as I sent it(as a char array, not a char pointer to an array).
I also need to specify that I'm using mikroC for PIC.
Here is my code as of right now:
char* GPS_sateliti;
char CsatInView[] =
"$GPGSV,3,2,11,14,25,170,00,16,57,208,39,18,67,296,40,19,40,246,00*74";
GPS_sateliti = GrupeazaDupaVirgule(CsatInView, 2);
char* GrupeazaDupaVirgule( char deGasit[],int nrVirgule ){
int cVirgule = 1;
char* pch = strtok (deGasit,",");
while (pch != 0)
{
pch = strtok (0, ",");
cVirgule++;
if(nrVirgule == cVirgule){
break;
}
}
return pch;
}
The function that operates on the char array received as a parameter in debug mode, before entering the function the char array is fine, after entering it, it seems to be empty
It may be that I should receive a pointer to an array of chars??
Any sort of advice is welcome.
Thank you
How should I correctly pass a "char string[]" to a function so that I may operate on a that parameter as I sent it(as a char array, not a char pointer to an array).
You can't. A function parameter of an array type always decays as the corresponding pointer type.
There are two idiomatic solutions to this.
1. a sentinel:
The last value in the array is a special value that marks the end. This is done in C with strings. They always end with a \0 character, that is guaranteed not to occur inside the string. The function can search for that character to know where the data ends.
(Note: with this info I have to add I'm not sure what your problem is. If you pass an "empty string", as literally "", the \0 will be there, so you shouldn't have a problem)
2. explicitly passing the size:
instead of just
void foo(int bar[]);
you define a function
void foo(size_t barSize, int bar[]);
The caller knows the size of the array, so it can just pass it along.
With a pointer :
char* arr;
yourFunction(arr);
If you wish to initialize it before :
char* arr = malloc(51 * sizeof(char)); // Allocate a memory place of 50 because strings are null terminated in C
yourFunction(arr);
An other way to allocate memory to an array :
char* arr = calloc(50, sizeof(char)); // Allocate 50 memory place which size if the size of a char
With a string :
char arr[50];
char* ptr = arr;
yourFunction(ptr);
You have to know that it is impossible in C to know the size of an array when using pointer. The only thing you can do is to parse the size of the string as a parameter :
size_t size = 50;
char arr[size];
char* ptr = arr;
yourFunction(ptr, size);
If you wish to understand in detail how pointer works and how to iterate them, may be this post can help you. I think it is very interesting.
Globally, you iterate through an array via a pointer like this :
for ( int i = 0; i < size; i++)
printf("Current pointed value in the array : %c\n", ptr[i]); // or arr[i]
I guess you understand why giving the size of a pointed array as a parameter is important. Sometimes you can avoid using this parameter like this :
for ( int i = 0; i != '\0'; i++) // Because strings are null-terminated in C.
// Do something

How to copy a char array in C?

In C, I have two char arrays:
char array1[18] = "abcdefg";
char array2[18];
How to copy the value of array1 to array2 ? Can I just do this: array2 = array1?
You can't directly do array2 = array1, because in this case you manipulate the addresses of the arrays (char *) and not of their inner values (char).
What you, conceptually, want is to do is iterate through all the chars of your source (array1) and copy them to the destination (array2). There are several ways to do this. For example you could write a simple for loop, or use memcpy.
That being said, the recommended way for strings is to use strncpy. It prevents common errors resulting in, for example, buffer overflows (which is especially dangerous if array1 is filled from user input: keyboard, network, etc). Like so:
// Will copy 18 characters from array1 to array2
strncpy(array2, array1, 18);
As #Prof. Falken mentioned in a comment, strncpy can be evil. Make sure your target buffer is big enough to contain the source buffer (including the \0 at the end of the string).
If your arrays are not string arrays, use:
memcpy(array2, array1, sizeof(array2));
If you want to guard against non-terminated strings, which can cause all sorts of problems, copy your string like this:
char array1[18] = {"abcdefg"};
char array2[18];
size_t destination_size = sizeof (array2);
strncpy(array2, array1, destination_size);
array2[destination_size - 1] = '\0';
That last line is actually important, because strncpy() does not always null terminate strings. (If the destination buffer is too small to contain the whole source string, sntrcpy() will not null terminate the destination string.)
The manpage for strncpy() even states "Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated."
The reason strncpy() behaves this somewhat odd way, is because it was not actually originally intended as a safe way to copy strings.
Another way is to use snprintf() as a safe replacement for strcpy():
snprintf(array2, destination_size, "%s", array1);
(Thanks jxh for the tip.)
As others have noted, strings are copied with strcpy() or its variants. In certain cases, you could use snprintf() as well.
You can only assign arrays the way you want as part of a structure assignment:
typedef struct { char a[18]; } array;
array array1 = { "abcdefg" };
array array2;
array2 = array1;
If your arrays are passed to a function, it will appear that you are allowed to assign them, but this is just an accident of the semantics. In C, an array will decay to a pointer type with the value of the address of the first member of the array, and this pointer is what gets passed. So, your array parameter in your function is really just a pointer. The assignment is just a pointer assignment:
void foo (char x[10], char y[10]) {
x = y; /* pointer assignment! */
puts(x);
}
The array itself remains unchanged after returning from the function.
This "decay to pointer value" semantic for arrays is the reason that the assignment doesn't work. The l-value has the array type, but the r-value is the decayed pointer type, so the assignment is between incompatible types.
char array1[18] = "abcdefg";
char array2[18];
array2 = array1; /* fails because array1 becomes a pointer type,
but array2 is still an array type */
As to why the "decay to pointer value" semantic was introduced, this was to achieve a source code compatibility with the predecessor of C. You can read The Development of the C Language for details.
You cannot assign arrays, the names are constants that cannot be changed.
You can copy the contents, with:
strcpy(array2, array1);
assuming the source is a valid string and that the destination is large enough, as in your example.
it should look like this:
void cstringcpy(char *src, char * dest)
{
while (*src) {
*(dest++) = *(src++);
}
*dest = '\0';
}
.....
char src[6] = "Hello";
char dest[6];
cstringcpy(src, dest);
I recommend to use memcpy() for copying data.
Also if we assign a buffer to another as array2 = array1 , both array have same memory and any change in the arrary1 deflects in array2 too. But we use memcpy, both buffer have different array. I recommend memcpy() because strcpy and related function do not copy NULL character.
array2 = array1;
is not supported in c. You have to use functions like strcpy() to do it.
c functions below only ... c++ you have to do char array then use a string copy then user the string tokenizor functions... c++ made it a-lot harder to do anythng
#include <iostream>
#include <fstream>
#include <cstring>
#define TRUE 1
#define FALSE 0
typedef int Bool;
using namespace std;
Bool PalTrueFalse(char str[]);
int main(void)
{
char string[1000], ch;
int i = 0;
cout<<"Enter a message: ";
while((ch = getchar()) != '\n') //grab users input string untill
{ //Enter is pressed
if (!isspace(ch) && !ispunct(ch)) //Cstring functions checking for
{ //spaces and punctuations of all kinds
string[i] = tolower(ch);
i++;
}
}
string[i] = '\0'; //hitting null deliminator once users input
cout<<"Your string: "<<string<<endl;
if(PalTrueFalse(string)) //the string[i] user input is passed after
//being cleaned into the null function.
cout<<"is a "<<"Palindrome\n"<<endl;
else
cout<<"Not a palindrome\n"<<endl;
return 0;
}
Bool PalTrueFalse(char str[])
{
int left = 0;
int right = strlen(str)-1;
while (left<right)
{
if(str[left] != str[right]) //comparing most outer values of string
return FALSE; //to inner values.
left++;
right--;
}
return TRUE;
}
Well, techincally you can…
typedef struct { char xx[18]; } arr_wrap;
char array1[18] = "abcdefg";
char array2[18];
*((arr_wrap *) array2) = *((arr_wrap *) array1);
printf("%s\n", array2); /* "abcdefg" */
but it will not look very beautiful.
…Unless you use the C preprocessor…
#define CC_MEMCPY(DESTARR, SRCARR, ARRSIZE) \
{ struct _tmparrwrap_ { char xx[ARRSIZE]; }; *((struct _tmparrwrap_ *) DESTARR) = *((struct _tmparrwrap_ *) SRCARR); }
You can then do:
char array1[18] = "abcdefg";
char array2[18];
CC_MEMCPY(array2, array1, sizeof(array1));
printf("%s\n", array2); /* "abcdefg" */
And it will work with any data type, not just char:
int numbers1[3] = { 1, 2, 3 };
int numbers2[3];
CC_MEMCPY(numbers2, numbers1, sizeof(numbers1));
printf("%d - %d - %d\n", numbers2[0], numbers2[1], numbers2[2]); /* "abcdefg" */
(Yes, the code above is granted to work always and it's portable)
for integer types
#include <string.h>
int array1[10] = {0,1,2,3,4,5,6,7,8,9};
int array2[10];
memcpy(array2,array1,sizeof(array1)); // memcpy("destination","source","size")
You cannot assign arrays to copy them. How you can copy the contents of one into another depends on multiple factors:
For char arrays, if you know the source array is null terminated and destination array is large enough for the string in the source array, including the null terminator, use strcpy():
#include <string.h>
char array1[18] = "abcdefg";
char array2[18];
...
strcpy(array2, array1);
If you do not know if the destination array is large enough, but the source is a C string, and you want the destination to be a proper C string, use snprinf():
#include <stdio.h>
char array1[] = "a longer string that might not fit";
char array2[18];
...
snprintf(array2, sizeof array2, "%s", array1);
If the source array is not necessarily null terminated, but you know both arrays have the same size, you can use memcpy:
#include <string.h>
char array1[28] = "a non null terminated string";
char array2[28];
...
memcpy(array2, array1, sizeof array2);
None of the above was working for me..
this works perfectly
name here is char *name which is passed via the function
get length of char *name using strlen(name)
storing it in a const variable is important
create same length size char array
copy name 's content to temp using strcpy(temp, name);
use however you want, if you want original content back. strcpy(name, temp); copy temp back to name and voila works perfectly
const int size = strlen(name);
char temp[size];
cout << size << endl;
strcpy(temp, name);
You can't copy directly by writing array2 = array1.
If you want to copy it manually, iterate over array1 and copy item by item as follows -
int i;
for(i=0;array1[i]!='\0';i++){
array2[i] = array1[i];
}
array2[i]='\0'; //put the string terminator too
If you are ok to use string library, you can do it as follows -
strncpy ( array2, array1, sizeof(array2) );

Printing an array of characters

I have an array of characters declared as:
char *array[size];
When I perform a
printf("%s", array);
it gives me some garbage characters, why it is so?
http://www.cplusplus.com/reference/clibrary/cstdio/printf/
This url indicates printf takes in the format of: `int printf ( const char * format, ... );
#include <stdio.h>
#include <string.h>
#define size 20
#define buff 100
char line[buff];
int main ()
{
char *array[100];
char *sep = " \t\n";
fgets(line, buff, stdin);
int i;
array[0] = strtok(line, sep);
for (i = 1; i < size; i++) {
array[i] = strtok(NULL, sep);
if (array[i] == NULL)
break;
}
return 0;
}
You declare an array of characters like so:
char foo[size];
You seem to have it mixed up with char *, which is a pointer to a character. You could say
char *bar = foo;
which would make bar point to the contents of foo. (Or, actually, to the first character of foo.)
To then print the contents of the array, you can do one of the following:
// either print directly from foo:
printf("%s", foo);
// or print through bar:
printf("%s", bar);
Note, however, that C performs no initialization of the contents of variables, so unless you specifically set the contents to something, you'll get garbage. In addition, if that garbage doesn't happen to contain a \0; that is, a char with value 0, it will keep on outputting past the end of the array.
Your array is not initialized, and also you have an array of pointers, instead of an array of char's. It should be char* array = (char*)malloc(sizeof(char)*size);, if you want an array of char's. Now you have a pointer to the first element of the array.
Why are we making such a simple thing sound so difficult?
char array[SIZE];
... /* initialize array */
puts(array); /* prints the string/char array and a new line */
/* OR */
printf("%s", array); /* prints the string as is, without a new line */
The char in array after the end of what you want to be your string (ie. if you want your string to read "Hello" that would be the next char after the 'o') must be the terminating NUL character '\0'. If you use a C function to read input that would automatically be appended to the end of your buffer. You would only need to worry about doing it manually if you were individually writing characters to your buffer or something for some reason.
EDIT: As with pmg's comment, the '\0' goes wherever you want the string to end, so if you wanted to shorten your string you could just move it up closer to the front, or to have an empty string you just have array[0] = '\0';. Doing so can also be used to tokenise smaller strings inside a single buffer, just as strtok does. ie. "Part1\0Part2\0Part3\0". But I think this is getting away from the scope of the question.
ie. you wanted to store the first 3 chars of the alphabet as a string (don't know why anyone would do it this way but it's just an example):
char array[4];
array[0] = 'a';
array[1] = 'b';
array[2] = 'c';
array[3] = '\0';
printf("%s\n", array);
If you have something like char array[] = "Hello"; the '\0' is automatically added for you.
char *array[size];
array is not a char * with that, it's more like a char ** (pointer to an array of chars, with is similar to pointer to pointer to char).
If all you need is a C string, either:
char array[size];
and make sure you 0-terminate it properly, or
char *array;
and make sure you properly allocate and free storage for it (and 0-terminate it too).

C comparing pointers (with chars)

Good evening, I have 2 functions and each of them accepts as argument a pointer to char:
char pointer[255];
func1(char* pointer)
{
...
memcpy(pointer,some_char,strlen(something));
return;
}
func2(char* pointer)
{
...
if (pointer==someother_char) exit(0); //FAILs
//also I have
if(pointer==someother_pointer2char); // FAILs
}
Now I've tried strstr,strcmp etc... doesn't work. Wanted to try memcmp but I don't have static len. As I have to compare char* to char and char* to char* I would be needing two solutions right?
So, how to compare these pointers (actually pointees) in shortest possible way?
Thanks.
E D I T
Thanks to wallacer and Code Monkey now for char* to char comparison I use following:
func1(char* ptr){
char someother_char[255];
char *ptr_char = NULL; //I have to strcmp a few values so this is why I initialize it first
...
ptr_char = someother_char;
if (strcmp(ptr,ptr_char) == 0) //gtfo and it does...
...
ptr_char = some2nd;
if(strcmp...
Any suggestions maybe... (hmm external function for comparing?)
Suggestion1(by Code Monkey)
#include <stdio.h>
int main(void) {
char tempchar[255];
tempchar[0] = 'a';
tempchar[1] = 'b';
tempchar[2] = '\0';
char *ptr_char;
ptr_char = &tempchar[0];
printf("%s", ptr_char);
return 0;
}
You need to use strcmp. Not seeing how you tried to use it, this is how you should use it:
char *someother_char = "a";
char *pointer = "a";
if (strcmp(pointer, someother_char) == 0) { // match!
}
else { // not matched
}
to then do the comparison with a char, you have to promote to a char*:
char *someother_char1;
char test = 'a';
char *pointer = "a";
strncpy((char*)test,someother_char1,sizeof(test));
if (strcmp(pointer, someother_char1) == 0) { // match!
}
else { // not matched
}
if you want to use the char array then you have to de-reference:
char char_array[255];
// don't forget to fill your array
// and add a null-terminating char somewhere, such as char_array[255] = '\0';
char *ptr_somechar = &char_array[0];
char *pointer = "a";
if (strcmp(pointer, ptr_somechar) == 0) { // match!
} else { // not matched
}
Well right off the bat, if you want to compare the pointees, you need to dereference them. This means to compare the actual char value, you'll have to call
if (*pointer == someother_char)
However this will only compare the first char in the array, which is probably not what you want to do.
To compare the whole thing strcmp should work
char* someother_str = "hello strstr";
if(strcmp(pointer, someother_str) == 0) {
// do something
}
Make sure your other string is declared as a char*
More info: http://www.cplusplus.com/reference/clibrary/cstring/strcmp/
Edit: as per your comment. comparing char* and char doesn't really make sense. One is a character value, the other is an address in memory. Do do so, you can either dereference the char* or reference the value variable.
char c;
char* ptr;
// dereference ptr
if ( c == *ptr ) {
...
}
// reference the value
if ( &c == ptr ) {
}
The first method checks if the values are the same. The second checks if ptr is in fact pointing to the memory containing c ie. is ptr a pointer to c
Hope that helps
Use function srtncmp no srtcmp.
int res = strncmp(str, "¿Cuál es tu nombre? ", 100);
See the next link
compare strings
Strings are null terminated. When you use such kind of strings, it's not a good idea to mixing with other memory copy functions.
Once you do the memcpy operation, please note that your destination string will not be null terminated.
memcmp is a fast operations. Otherwise yo can simply loop through each character and quit upon finding a difference.
To use strcmp, please make sure that both the strings are null terminated. Otherwise it will lead to some crash.
I suggest you to use string functions like strcmp,strlen, strcpy to deal with strings because for that it's actually implemented.
You can't compare two pointers unless both pointers are referring to same memory location. Pointer is just a address to a memory location. What you really want to do is that, to compare the contents rather than compare the address where it's stored. So please use strcmp but again I warn you make sure that it's null terminated.

Resources