-4

I have a variable str which is "Hello Me".

I want to write a program that will only display the first 5 characters of the string, which is Hello.

Below is a snippet of my code in which I am attempting to do this.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <malloc.h>
#include <string.h>

int main(int argC, char **argV)
{
        char str[100]="Hello Me";
        char c[100];
        sprintf(c,"%s\n",str[1,4]);
        printf("string is %s\n",str);
}

Unfortunately when attempting to do this I got a segmentation fault error. How do I tweak the program to get the desired results. I need to display characters like c as an array.

jms1980
  • 1,017
  • 1
  • 21
  • 37
  • 1
    `str[1,4]` is the same as `str[4]`, which is a single character, not a string. That's the reason for the segfault. To fix it, try `sprintf(c, "%.5s\n", str);`. Of course, you'll have to print `c` in the printf to see the results. – user3386109 Apr 21 '21 at 23:39
  • Now what do I do if I want to start the string off with the second character so it would c would equal ello for example? – jms1980 Apr 21 '21 at 23:47
  • Tip: `char* str = "..."`. Don't bother with the `[100]` unless you need a *mutable* buffer. You an have it auto-sized like `char str[] = "..."`. – tadman Apr 21 '21 at 23:55
  • Does this answer your question? [Strings in C, how to get subString](https://stackoverflow.com/questions/2114377/strings-in-c-how-to-get-substring) – tadman Apr 21 '21 at 23:56

2 Answers2

0

To print only five characters from a string:

printf("The first five characters are %.5s\n", the_string);

There's no need to copy the string to do that. (Note the difference between the format %.5s, which is "if the string argument is longer than five characters, use only the first five.", and %5s, which is "if the string is shorter than five characters, first output enough spaces to make the total width five." These two options are independent of each other,, so you can use both: %7.5s would be "use at most five characters, and place them at the right-hand side of a seven-character field. If you want to pad on the right instead of the left, use a minus sign.)

In fact, there is much less need to copy strings than you might think. Unnecessary copying is time-consuming and error-prone. It is also surprisingly common. So you should always ask yourself if a copy is really necessary.

If you decide that a copy really is necessary, your first point of call is strndup, which dynamically allocates exactly enough storage for a substring of a specified size:

char* strndup(const char* original, size_t n);

That lets you do things like:

char* first_five = strndup(the_string, 5);

(If the_string only has three characters, for example, that's not a problem. You'll get all three of them.)

Or, if you want a substring from the middle of the string:

char* substring = strndup(the_string + start, length);

This is not quite as safe, since there is no way that strndup can verify that the_string has at least start characters. To make it safer, you could do this:

char* substring = strndup(the_string + strnlen(the_string, start), length);

If you really really know that start is in range, you don't have to do that. Counting the first start characters, which is what strnlen does, is not very efficient. But it's better than counting all the characters, which is what strlen does.

(If you think the_string + start looks odd, remember that it is exactly the same as &the_string[start]; that is, it is the address of element start in the array the_string.)

You should always use strndup if possible, because it's the only moderately standard function which is (reasonably) safe. It's (reasonably) safe because it doesn't depend on your knowing that the destination string is big enough. Unfortunately, it (and strnlen) are not yet part of thne C standard (although they're coming soon, I believe), and they were only added to Posix in the 2008 revision. But they've been available for a long time on Linux and for several years now on Mac OS X.

You will need to use the correct feature-test macro, though:

#define _POSIX_C_SOURCE 200809L

or

 #define _XOPEN_SOURCE 700

That has to go before any #include in the file which uses the function. If you're using clang or gcc, you can add a -D option to your compile command.

If you need Windows compatibility, you'll have to find an open source implementation; fortunately, that's not too hard:

rici
  • 234,347
  • 28
  • 237
  • 341
0

You may build a slice function, which has four inputs, dst string, src string, slice start pos, slice end pos.

Notice the index should be in the range of src string length.

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

char *
slice_str (char *buffer, char *str, int start, int end)
{
  int j = 0;
  for (int i = start; i <= end; ++i)
    {
      buffer[j++] = str[i];
    }
  buffer[j] = 0;
  return buffer;
}

int
main (void)
{
  char *str = "abcdef";
  int len = strlen (str);
  char ostr[len + 1];
  int start;
  int end;
//index
  start = 1;
  end = 2;
  slice_str (ostr, str, start, end);
//show
  printf ("%s\n--------------\n|index %d to %d|\n--------------\n%s\n", str,
          start, end, ostr);
  return 0;
}
LinconFive
  • 1,718
  • 1
  • 19
  • 24