-3

I'm trying to obtain the n-th character from a string. However, it's returning me the string from the n-th character onwards.

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

char *test(char input[],int position){

    char *result= malloc(sizeof(char)*100);
    result=&input[position];
    return result;
}

int main(){
    char *k;
    k=test("abcdefghi\n",3);
    printf("%s",k);
}

The above code returns defghi instead of just d. I'm not sure what's wrong here.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
sassyfox
  • 1
  • 2
  • 7
    If your function is supposed to return a character (a `char`), why are you having it return `char *` (a pointer to `char`)? Along the same lines, if you want to print a character, why are you using `%s` (print a string), not `%c` (print a character)? – Steve Summit Nov 02 '21 at 16:07
  • 3
    Also, I doubt you'll need to use `malloc` at all. – Steve Summit Nov 02 '21 at 16:09
  • 3
    You're leaking memory, since you overwrite the `result` value that was returned from `malloc()`. – Barmar Nov 02 '21 at 16:10
  • If you really want to receive the character as offset of given string (`input + position` would be simpler, by the way) you could the print this single character via `printf("%c", *k);` – note that you need to dereference the pointer... – Aconcagua Nov 02 '21 at 16:21

4 Answers4

2

You're confusing strings and characters. You probably want this:

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

char test(char input[], int position){
   return input[position];
}

int main(){
    char k = test("abcdefghi\n",3);
    printf("%c", k);
}

This will print

d

This is so simple you don't actually need a function. Usually you have a pointer to a string or an array of characters and you just can pick the nth character like this:

char sometext[] = "abcdefghi\n";
...
char k = sometext[3];
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
2

You should probably just return a single char as shown in other answers.

But if you're really required to return char *, here's how you should do it.

You only need to allocate 2 characters -- one for the character you're returning, and one for the trailing null byte.

You need to copy the character into the allocated memory, not reassign the pointer variable.

char *test(char input[],int position){
    char *result= malloc(2);
    result[0] = input[position];
    result[1] = '\0';
    return result;
}

The caller should free the memory after printing it.

int main(){
    char *k;
    k=test("abcdefghi\n",3);
    printf("%s\n",k);
    free(k);
}
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • While technically correct I don't think it's a good idea to return a single character embedded in a string, needlessly slow for memory allocation and error prone (at some point of time someone *will* forget to free...). – Aconcagua Nov 02 '21 at 16:23
  • There was already another answer showing how to do it with a `char`. I thought this would be instructive to show what they're doing wrong when they try doing it with `char *`. – Barmar Nov 02 '21 at 16:26
  • Accepting the argument – and recommending to add to the answer why this solution is problematic (see my comment) and maybe link to the other answer... – Aconcagua Nov 02 '21 at 16:29
  • I've updated the answer to specify the context. – Barmar Nov 02 '21 at 16:30
2

I'm trying to obtain the n-th character from a string. However, it's returning me the string from the n-th character onwards.

The function

char *test(char input[],int position){

does not return a character. It returns a pointer.

Moreover the function has a memory leak because at first there is allocated memory and its address is assigned to the pointer result and then the pointer is reassigned

char *result= malloc(sizeof(char)*100);
result=&input[position];

So the address of the allocated memory is lost.

Apart from this the parameter position can have a value that exceeds the length of the passed string. So the function can invoke undefined behavior.

If the function returns a pointer to a character then to output the pointed character you need 1) to dereference the pointer and 2) to use the conversion specifier %c instead of %s in a call of printf.

Also as the passed string is not being changed within the function then the corresponding parameter should be declared with the qualifier const.

The function can be declared and defined the following way

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

char * test( const char input[], size_t position )
{
    char *result = NULL;

    if ( position <= strlen( input ) )
    {
        result = ( char * )( input + position );
    }

    return result;
}

And in main you should write

char *k;

k = test( "abcdefghi\n", 3 );

if ( k != NULL ) printf( "%c\n", *k );
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • I personally would feel better to retain constness on returned pointer as well, consider `*k = 0;` in last example (so trading safety against convenience). – Aconcagua Nov 02 '21 at 16:49
  • In a perfect world I'd actually [overload](https://stackoverflow.com/a/25026358/1312382) – admitted, likely beyond the QA's horizon... – Aconcagua Nov 02 '21 at 16:51
  • @Aconcagua It is not C++. It is C where function overloading is absent. So all C Standard string functions follow the general convention that they return a non-constant pointer to constant strings. For example look at the declaration of the function strchr char *strchr(const char *s, int c); – Vlad from Moscow Nov 02 '21 at 16:51
  • You didn't follow my link, did you? They *do* exist since C11, at least *kind of* (and yes pretty unhandy). And yes, I know that pattern existing in the standard – and never agreed on, thus wouldn't follow it at custom functions either, weighing safety higher (I assume that pattern only exists for compatibility reasons anyway, not to break existing code that doesn't deal with constness – but that's not a matter with custom functions being developed and called with `const` keyword existing since long...). – Aconcagua Nov 02 '21 at 17:03
  • 1
    @Aconcagua It will be too complicated for such a simple question of a beginner. – Vlad from Moscow Nov 02 '21 at 17:05
  • I know – *'perfect world'*, *'beyond horizon'* – assumed it was clear that I didn't want to have that integrated in the answer. Seems as if I need to fine-tune my wordings ;) – Aconcagua Nov 02 '21 at 17:09
0

If you want to duplicate the string from the n-th position:

char *copyFronNthPosiztion(const char *input, size_t position)
{
    size_t len = strlen(input);
    char *result = NULL;
    if(position < len)
    {
        result = malloc(len - position + 1);
        strcpy(result, input + position);
    }
    return result;
}

If you want to have n-th character you do need any functions. Just use n-th index.

If you want to have a single char string:

#define NTH(str, pos)   ((char[]){(str)[pos], 0})

    k=NTH("abcdefghi\n",3);
    printf("%s",k);
0___________
  • 60,014
  • 4
  • 34
  • 74