2

I have a character pointer that points the begining of a string and an index less than the length of the string. Now I want to create a pointer to point a substring of original string from the begining to the index or a substring with above constraints. Please help me to find a way to get it done. Here is a bit of the code:

char* ch="323+465";//this is the original string
int index=2;  //this is the index upto which I wish to create a substring, 
              // in java, it would have been ch.substring(0,3), if ch were a String

Thanks in advance.

Victor Mukherjee
  • 10,487
  • 16
  • 54
  • 97
  • 2
    Do you need to preserve the original string? – Kerrek SB Sep 13 '12 at 12:39
  • yes, actually i need to divide it into three substrings, two numbers and one sign. – Victor Mukherjee Sep 13 '12 at 12:42
  • 2
    Maybe `strtok` will be more appropriate for your case than the general solution via copying. You have to be the judge of that. `strtok` will overwrite the *delimiters* with zeros, but it'll leave everything else intact. – Kerrek SB Sep 13 '12 at 12:43

5 Answers5

1

You can't do that without creating 3 strings. The char point only marks the beginning of the string, so you would need to combine a pointer and an index into a new type. Remember you don't have strings in C. In languages like Java (and others) will create copies of the sub string anyway.

struct pseudo_string { char *s, int index; } vstring[3];
char* ch="323+465";
vstring[0].s = ch;
vstring[0].index = 2;
vstring[1].s = ch + index + 1;  // weird
vstring[1].index = 1;
vstring[2].s = vstring[1].s + 1;
vstring[2].index = 2;

So it is overly complex and useless. In this case index is being used as counter...

If you want to keep the same base pointer, you gonna need 2 indices or 1 index and a len:

struct pseudo_string2 { char *s; int start; int end; };

But that's an overkill for small strings.

If don't want to use malloc, you can try to use a matrix:

char vstring[3][10]={0};
strncpy(vstring[0], ch, 3);
strncpy(vstring[1], ch+3, 1);
strncpy(vstring[2], ch+4, 3);

The advantage of the matrix, even if you waste few bytes, is that you don't need to deallocate it. But if you need to use these values outside this function, than you don't have another scape than to use malloc and free (don't consider globals for that ;-).

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char * substr(char *s, int start, int end)
{
       int size = end - start + 2; // 1 for the inclusive limits and another 1 for the \0
       char * r = (char*)malloc(size);
       strncpy(r,s+start, size-1);
       r[size-1]=0;
       return r;
}
int main()
{
    char* ch="323+465";
    char *parts[3];
    parts[0] = substr(ch, 0,2);
    parts[1] = substr(ch, 3,3);
    parts[2] = substr(ch, 4,6);
    printf("%s %s %s\n", parts[0], parts[1], parts[2]);
    free(parts[0]);
    free(parts[1]);
    free(parts[2]);
}
nmenezes
  • 910
  • 6
  • 12
0

Make a copy of a suitable number of characters:

char * substr = malloc(index + 2);
strncpy(substr, ch, index + 1);
substr[index + 1] = 0;

// ...

free(substr);

If you're happy to mutilate the original string, just insert a null byte:

ch[index + 1] = 0;

The odd + 1 comes from the fact that your index seems to be inclusive, which is generally a bad idea.

Community
  • 1
  • 1
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
0

You can't, because that would imply modifying the string literal, which is illegal.

Alternative:

char ch[]="323+465";
int index=2;
ch[index] = '\0'; 
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • 1
    I think he wants a substring of the original string. – Lews Therin Sep 13 '12 at 12:41
  • Yes, but he wants the beginning of the string. If he wanted the end, he could just increment the pointer, but he has to insert a new null terminator to get it from the beginning to the desired index. – mtsvetkov Sep 13 '12 at 12:42
0

First, make the string writable by using a char array instead of a pointer to a string literal. Then

char ch[] = "323+456";

int idx = 2;
ch[idx] = 0; /* Now ch holds the string "32" */

You should avoid an identifier clash with the classic BSD index function, that's why I used idx instead.

This solution assumes it is okay to modify the original string. If not, you need to allocate a new string first.

Jens
  • 69,818
  • 15
  • 125
  • 179
0

the same behavior of java substring (allocates new string)

 char* res = (char*)malloc(index+2);
 strncpy(res,ch,index+1);
 res[index+1]='\0';

I see that you try to delimit by +, so easier is to use strtok :

 char ch[] ="323+465";
 char * res;
 res = strtok (ch,"+");
 // res= 323
Michael
  • 2,827
  • 4
  • 30
  • 47
  • do you really need this "res[index]='\0';"?you are already allocating an extra char space for NULL.strncpy automatically attaches a NULL.no need to exclusively do it. – Vijay Sep 13 '12 at 12:52
  • @sarathi: No null-character is implicitly appended to the end of destination, so destination will only be null-terminated if the length of the C string in source is less than num. (source is larger then dest) – Michael Sep 13 '12 at 12:56