How to break a string in C with / - c

I have a string with the following pattern :
char *str = "ai/aj/module_mat.mod";
and I want to select module_mat as my final string for the further logic. I have tried to used rindex() so that I can get the final part of the string. But I am not able to do this in C. What am I doing wrong?
The code I am trying is -
char *first = rindex(str, "/");
char *first = strtok(first, ".");

Your mistake is right here:
char *str = "ai/aj/module_mat.mod";
Since str points to a constant, this should be:
const char *str = "ai/aj/module_mat.mod";
Now your compiler should show you the other problems.
Similarly:
char *first = rindex(str, "/");
Since rindex is returning a pointer into the constant you passed it, that pointer should also be const.
char *first = strtok(first, ".");
Hmm, what do the docs for strtok say:
If a delimiter byte is found, it is overwritten with a null byte
to terminate the current token, and strtok() saves a pointer to the following byte; ...
So strtok modifies the thing the pointer points to, so passing it a pointer to a constant is bad! You can't modify a constant.

First off, the string literal is immutable, so it is very dangerous to bind it to a mutable char pointer. First fix your code:
const char* str = "ai/aj/module_mat.mod";
Next, use strchr:
#include <string.h>
const char* p = strchr(str, '/');
if (p != NULL) {
++p;
printf("Last part: %s\n", p);
} else {
printf("No '/' found in string %s.\n", str);
}
If a / is found in the string, p will point to it, and hence p can be used as the suffix substring of the original string, and there's no need to modify the original string. We advance p by one to skip past the / and are left with the final part of the string.

Related

Strange behaviour when implementing strcat in C

I'm trying to implement the strcat function myself. Here's my code:
char *my_strcat(char *dst, const char* src) {
char *tmp = dst;
while(*tmp) {
tmp ++;
}
while(*tmp++ = *src++);
return dst;
}
However, when I try to test this function, I get only the src string. (i.e. I'm expecting to get dst+src, but the returned value is the same as src)
As we can tell from the code, in the first while loop, I'm trying to move tmp pointer to the end of dst.
However,
I tried to add a printf in the first while loop, nothing is printed out, which indicates that it didn't even entered the loop.
Then I tried to used if (*tmp == '\0') print something, and found that *tmp == '\0' is true.
But I'm pretty sure that tmp is a non-empty string, so *tmp should point to the first character of the string (I think). So I'm feeling confused about it. Can anyone tell why this happens and how can I fix it?
Edit:
The calling code is
char *subpath = "";
subpath = my_strcat(subpath, path);
path is a const char* read from the command.
Do I need to assign the value back to subpath? Or just calling my_strcat is enough?
There are two problems here:
char *subpath = "";
subpath = my_strcat(subpath, path);
subpath points to a string of length 0, there is not enough space to append anything.
subpath points to a string literal and writing into string literals is undefined behaviour, on modern desktop platforms your program usually crashes.
You want something like this:
char subpath[100] = "";
char *foo;
foo = my_strcat(subpath, path);
or just
char subpath[100] = "";
my_strcat(subpath, path);
or
char subpath[100] = "Hello ";
my_strcat(subpath, "world!");
printf("%s\n", subpath); // prints Helllo World!

How to fix gibberish printed after use strtok

I have uni project, I need to check if the syntax is right. I get pointer to a string, and check if the first token acceptable. In case it's OK, i move forward. But in case it's not OK, i need to print what is wrong.
What i did is to create a buffer since i can't change the original string.
After that i use strtok to cut the buffer, and look if the token i got is acceptable.
char *str = "sz = 12345";
printf("The check of MACRO: %d\n", isMacro(str));
int isMacro(char *str)
{
char buf = NULL;
char *token;
strcpy(&buf,str);
token = strtok(&buf," ");
printf("You here, value token is %s\n",token);
}
I expected that printf would print the 'sz' but it prints:
You here, value str is sz<▒R
char buf = NULL;
This is a type error. buf is a single character, but NULL is a pointer value. You can't store a pointer in a char.
strcpy(&buf,str);
This code has undefined behavior (unless str happens to be an empty string). buf is not a buffer, it is a single char, so it does not have room to store a whole string.
If you want to make a copy of a string, you need to allocate enough memory for all of its characters:
You could use strdup (which is in POSIX, but not standard C):
char *buf = strdup(str);
if (!buf) {
... handle error ...
}
...
free(buf);
You could replicate strdup manually:
char *buf = malloc(strlen(str) + 1);
if (!buf) {
... handle error ...
}
strcpy(buf, str);
...
free(buf);
You could use a variable-length array (but you're limited by the size of your stack and you have no way to check for errors):
char buf[strlen(str) + 1];
strcpy(buf, str);
...
buf is a single char instead of a pointer to a char. In fact, if you're planning to do strcpy to copy a string to it, you need to allocate memory first using malloc. Instead I'd suggest you to use a function like strdup instead of strcpy to create a copy of the original string to modify it using strtok. Remember to free the strduped string later.
Something like this.
int isMacro(char *str)
{
char *buf = NULL;
char *token;
buf = strdup(str);
token = strtok(buf," ");
printf("You here, value of token is %s\n",token);
free(buf);
}

C - Truncate char* string argument

I've been trying to do this simple task for a while now but can't get it to work properly as I'm not super familiar with pure C tricks.
Basically I have a function that get called by a block of code that I didn't write myself and can't edit.
int myMethod(char* str);
My task is to find the position of a substring in the char* and if found get the string from index 0 to index of the found substring and assign it to the original char* str.
Here is what I tried to do:
int myMethod(char* str)
{
int splitPos = strstr(str, "Pikachu") - str;
char buffer[splitPos + 1];
strncpy(buffer, str, splitPos);
buffer[splitPos] = '\0';
memcpy(str, buffer, strlen(buffer) + 1);
}
And I get a SegFault at the last strcpy call. I tried changing it to the followings with the same result
memmove(str, buffer, ...)
strcpy(...)
There are multiple problems in your function:
you do not check the return value of strstr for success. Your code has undefined behavior if it fails to locate the substring.
strncpy will not null terminate the destination string if the source is longer than splitPos-1, which it is. Do not use strncpy, it does not do what you think, it is very error prone for both the programmer and the reader. For your purpose, memcpy with the same arguments is equivalent and less problematic.
strlen(buffer) is redundant, it evaluates to splitPos.
You actually do not need a temporary buffer for your goal: truncating the string can be done by simply setting the start of the substring to '\0'.
if the destination string is read-only, modifying it has undefined behavior, and might explain the observed segmentation fault.
Here is a simplified version:
int myMethod(char *str) {
char *p = strstr(str, "Pikachu");
if (p != NULL) {
*p = '\0';
}
}
Conversely if you just need to manipulate the substring in further code in myMethod, you can make a copy to avoid the fateful attempt at modifying the original string:
int myMethod(char *str) {
char *p = strstr(str, "Pikachu");
size_t len = p ? p - str : stren(str);
char buffer[len + 1];
memcpy(buffer, str, len);
buffer[len] = '\0';
str = buffer;
/* use `str` in this function */
}

c copying first letter of ptr

I have no idea what is wrong with the following code. I perused stackoverflow without finding much assistance.
char * abbreviate_name( const char * full_name) {
int length = strlen(full_name) + 1;
char * final = malloc(length);
*answer = '\0';
char ptr[51];
// above is where I declare all my variables
strncpy(ptr, full_name, length); // copy full_name because it is a const
// ...
final = &ptr[1]; // this line copies all of ptr when I do a prinf on it
I'm just wondering how to get the first letter of ptr.
I tried playing with the ptrs and addresses and couldn't get it to work.
to get the first char of a pointer you can either go *ptr or ptr[0].
Your code has other problems though, assign to final doesn't copy, it just points final to another location, in this case you are going to point to a stack variable and it's going to fail badly.
instead, just strcpy into final and get rid of "ptr"
final[0] = ptr[0];
*final = *ptr;
final[0] = *ptr;
*final = ptr[0];
You can, in addition to Keith's answer, accomplish the allocation and copy of full_name to final in one step by making use of strdup:
char *abbreviate_name (const char *full_name) {
char *final = strdup (full_name);
...
strdup will call malloc to dynamically allocate storage sufficient to hold full_name. Just as if you had used malloc, you are responsible for freeing the memory when it is no longer needed.
I am probably shooting in the dark and writing an answer which is very much prone to down-votes, but let me begin.
Probably OP is looking for a function which provides and abbreviated version of a string, thus first letter of each of the given words in a string ( full_string ). reason I thought this because of char * return type and function name.
char * abbreviate_name( const char * full_name) ;
If I am correct in understanding the question, then you are probably looking for
strtok
and here is a snippet for extracting what you are looking for
char *str1, *saveptr1, *token ;
for ( str1 = full_name; ; str1 = NULL) {
token = strtok_r(str1, " " , &saveptr1); // delimited with " "
if ( token == NULL ) {
break; // break once no tokens available
}
printf("%c ", *token); // Extract first letter for each word, which probably form the abbreviated string you are looking for
}

What is the meaning of a "*" before a string in C?

I am trying to understand this algorithm, which reverses a C-style character in-place. I don't understand what the * indicates in the context of being before a string and in the context of "char * end." Thanks for your help!
void reverse(char *str) {
char * end = str;
char tmp;
if (str) {
while (*end) {
++end;
}
--end;
while (str < end) {
tmp = *str;
*str++ = *end;
*end-- = tmp;
}
}
}
You are really interested in learning then you need to learn basic of c first then pointer:
This one is a very quick tutorial of pointers : http://www.programiz.com/c-programming/c-pointers then go through this and see string as pointer : https://www.cs.bu.edu/teaching/c/string/intro/
I will suggest to go through them once help you in understanding many things in other languages also. :)
It's a character pointer when you use a "" before a string..
This is also treated as character array where the string entered after"" will be the name of that array.
The asterisk refers to a pointer
char tmp
This is a character
char * str
This is a pointer to a char (or char array in this case).
tmp = *str;
Means that the character tmp is filled with the first character from the string array pointed to by the pointer str.

Resources