Reversible array in c - will not print -

The problem with this code is that it actually doesn't print anything after the user types some text on the command line.

The purpose of the code is to accept the number of lines that the user enters through the command line after the file name. Then the user will enter something in the reverse order. The program should cancel user input for each line.

Input example = big red dog

Example Result = red dog

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define SIZE 80

char * reverseWords(char *string);

//argc is the count of cmd arguments.
//each command line argument is of type string
int main(int argc, char *argv[]){

    //initialize local variables
    int i;
    int N;
    char str[SIZE];

    for(i = 1; i <argc; i++)
    {
        //set N equal to the users number in the command line 
        N = atoi(argv[i]);
    }

    if(argc != 2){//2 means that something is in the argument.
        printf("ERROR: Please provide an integer greater than or equal to 0");
        exit(1);//exit the program
    }else if(N < 0){//We cant have a negative array size.
        printf("ERROR: Please provide an integer greater than or equal to 0");
        exit(1);//exit the program
    }else{
        for(i = 0; i < N; i++){
            /*
            fgets(pointer to array, max # of chars copied,stdin = input from keyboard) 
            */
            fgets(str,SIZE,stdin);

            printf("%s", reverseWords(str)); //<---does not print anything....
        }           
    }
    return 0;
}   


char * reverseWords(char *line){

    //declare local strings 
    char *temp, *word;
    //instantiate index
    int index = 0;
    int word_len = 0;
    /*set index = to size of user input
        do this by checking if the index of line is
        equal to the null-character.
    */
    for(int i = 0; line[i] != '\0';i++)
    {
        index = i;//index = string length of line.
    }

    //check if index is less than 0.
    //if not we decrement the index value.

    for(index; index != -1; index--){
        //checking for individual words or letters
        if(line[index] == ' ' && word_len > 0){
            strncpy(word,line,word_len);
            strcat(temp , (word + ' '));
            word_len = 0;

        }else if(isalnum(line[index])){
            word_len == word_len+1;
        }//end if

    }//end loop

    //copy over the last word after the loop(if any)
    if(word_len > 0){
        strncpy(word,line,word_len);
        strcat(temp,word);
    }//end if
    line = temp;
    return line;
}//end procedure 
+6
source share
4 answers

It should not be surprising that reverseWordsit does not print anything. Why?

char * reverseWords(char *line){
    ...
    char *temp, *word;
    ...
    line = temp;
    return line;
} //end procedure

line? ( temp). temp? ( reverseWords). temp (none - )

, , reverseWords, ? ( ...), , - char temp[strlen(line)+1] = "";, reverseWords Undefined Behavior, , , - reverseWords, , reverseWords ...

? : (1) , :

char *revwords (char *rline, char *line)

(2) temp, , temp, reverseWords

(3) temp reverseWords line temp . (, strcpy line = temp;)

, reverseWords , , , reverseWords.

, argc argv , main . , stdin,

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

#define SIZE 256

char *revwords (char *rline, char *line);

int main (void) {

    char line[SIZE] = "", rline[SIZE] = ""; /* storage for line/rline */

    while (fgets (line, SIZE, stdin)) { /* for each line on stdin */
        printf ("\n line: %s\nrline: %s\n", line, revwords (rline, line));
        *rline = 0; /* set first char in rline to nul-byte */
    }

    return 0;
}

char *revwords (char *rline, char *line)
{
    size_t lnlen = strlen (line);   /* length of line */
    /* pointer, end-pointer, rev-pointer and flag pointer-to-space */
    char *p = line + lnlen - 1, *ep = p, *rp = rline, *p2space = NULL;

    if (!line || !*line) {  /* validate line not NULL and not empty */
        fprintf (stderr, "revwords() error: 'line' empty of null.\n");
        return NULL;
    }

    if (*ep == '\n')    /* if line ends in '\n' -- remove it */
        *ep-- = 0;
    else                /* warn if no '\n' present in line */
        fprintf (stderr, "warning: no POSIX '\\n' found in line.\n");

    for (; ep >= line; ep--) {  /* for each char from end-to-beginning */
        if (*ep == ' ') {               /* is it a space? */
            size_t len = p - ep;        /* get the length of the word */
            strncat (rp, ep + 1, len);  /* concatenate word to rline  */
            if (p == line + lnlen - 1)  /* if first word, append ' '  */
                strcat (rp, " ");
            p = ep;                     /* update p to last ' '  */
            p2space = ep;               /* set flag to valid pointer */
        }
    }
    strncat (rp, line, p - line);       /* handle first/last word */

    if (!p2space) { /* validate line contained ' ', if not return NULL */
        fprintf (stderr, "revwords() error: nothing to reverse.\n");
        return NULL;
    }

    return rline;   /* return pointer to reversed line */
}

:, line '\n', revwords, , , SIZE ( , POSIX '\n' ), . .

/

$ printf "my dog has fleas\nmy cat does too\n" | ./bin/str_rev_words

 line: my dog has fleas
rline: fleas has dog my

 line: my cat does too
rline: too does cat my

, - . , , , . .

, - :

char *revwords (char *rline, char *line)
{
    /* length, pointer, end-pointer, pointer-to-space, copy of line */
    size_t len = strlen (line);
    char *p = NULL, *p2space = NULL, copy[len+1];

    if (!line || !*line) {  /* validate line not NULL and not empty */
        fprintf (stderr, "revwords() error: 'line' empty of null.\n");
        return NULL;
    }

    if (line[len-1] == '\n')    /* remove trailing newline */
        line[--len] = 0;
    else                /* warn if no '\n' present in line */
        fprintf (stderr, "warning: no POSIX '\\n' found in line.\n");

    strncpy (copy, line, len + 1);  /* copy line to 'copy' */

    /* for each ' ' from end-to-beginning */
    while ((p = strrchr (copy, ' '))) {
        strcat (rline, p + 1);          /* append word to rline */
        strcat (rline, " ");            /* followed by a space  */
        p2space = p;                    /* set p2space to p     */
        *p2space = 0;                   /* nul-terminate copy at p */
    }

    if (p2space) {              /* validate space found in line */
        *p2space = 0;           /* nul-terminate at space       */
        strcat (rline, copy);   /* concatenate first/last word  */
    }
    else {                      /* no ' ' in line, return NULL  */
        fprintf (stderr, "revwords() error: nothing to reverse.\n");
        return NULL;
    }

    return rline;   /* return pointer to reversed line */
}

.. , C caMelCase MixedCase . caMelCase MixedCase java ++. ( , , - )

+6

, .

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

char* reverse_words(char* str);

int main() {
    char arr[] = "the big red dog"; 
    printf("%s", reverse_words(arr));
    return 0;
}


char* reverse_words(char* str) {
    char delim = ' '; // space  
    int left = 0;
    int reverse_index = 0;
    int right = 0;
    int len = strlen(str);
    char tmp;
    while (left < len) {
        while  (str[right] != delim && right < len)
            right++;    
        reverse_index = right - 1;
        while (left < reverse_index){
            tmp = str[left];
            str[left] = str[reverse_index];
            str[reverse_index] = tmp;
            left++;
            reverse_index--;
        }
        right++;        
        left = right;
    }

    strrev(str);
    return str;
}


//output is: dog red big the

,

char* strrev(char *str) {
  char *p1, *p2;

  if (! str || ! *str)
        return str;

  for (p1 = str, p2 = str + strlen(str) - 1;
                          p2 > p1; ++p1, --p2) {
        *p1 ^= *p2;
        *p2 ^= *p1;
        *p1 ^= *p2;
  }

  return str;

}

,

char* strrev(char *str) {
    int left = 0;
    int right = strlen(str) - 1;
    char tmp;
    while(left < right) {
        tmp = str[left];
        str[left] = str[right];
        str[right] = tmp;
        left++;
        right--;
    }

    return str;
}
+1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define SIZE 80

char *reverseWords(char line[SIZE]){
    char temp[SIZE];
#if SIZE > 255
    unsigned index[SIZE];
#else
    unsigned char index[SIZE];
#endif
    int i, index_count = 0;
    int inside_word = !!isalpha((unsigned char)line[0]), word = inside_word;

    for(index[index_count++] = i = 0; line[i]; ++i){//copy & make index table
        unsigned char ch = temp[i] = line[i];
        if(inside_word && !isalpha(ch) || !inside_word && isalpha(ch)){//Edge
            index[index_count++] = i;
            inside_word = !inside_word;
        }
    }
    index[index_count] = i;

    int last_word_index = index_count - 1;//last index
    last_word_index -= !word  ^ (last_word_index & 1);//to word

    char *p =line;
    for(i = 0; i < index_count-1; ++i){
        int len;
        if(word){
            len = index[last_word_index+1] - index[last_word_index];
            memcpy(p, &temp[index[last_word_index]], len);
            last_word_index -= 2;
        } else {
            len = index[i+1] - index[i];
            memcpy(p, &temp[index[i]], len);
        }
        word = !word;
        p += len;
    }

    return line;
}

int main(void){
    char str[SIZE];

    while(fgets(str, sizeof str, stdin)){
        printf("%s", reverseWords(str));
    }
}
0

, string.h, strlen. , malloc calloc - .

reverseWords.

char *myrev(const char *line)
{
    char *revword(char *);

    size_t i = strlen(line);
    int inword = OUT;

    size_t nWord = 0, nallocWord;
    char *word;     // will store the word

    size_t nRet = 0, nallocRet;
    char *ret;      // will store the entire line, but reversed

    // establish preconditions
    assert(i > 0);
    assert(line != NULL);

    // alloc memory for word and ret
    if ((word = malloc(nallocWord = INITALLOC)) != NULL && 
                (ret = calloc(nallocRet = INITALLOC, sizeof(char))) != NULL) {

        // walk backwards through line
        while (i--) {
            if (inword == OUT && isalnum(line[i]))
                inword = IN;    // we just entered a word

            if (inword == IN && isalnum(line[i])) {
                // we're inside a word; append current char to the word buffer
                word[nWord++] = line[i];

                // word buffer exhausted; reallocate
                if (nWord == nallocWord)
                    if ((word = realloc(word, nallocWord += ALLOCSTEP)) == NULL)
                        return NULL;
            }

            // if we are in between words or at the end of the line
            if (i == 0 || inword == IN && isspace(line[i])) {
                inword = OUT;
                word[nWord] = '\0';

                word = revword(word);

                // ret buffer exhausted; reallocate
                if (nRet + nWord > nallocRet)
                    if ((ret = realloc(ret, nallocRet += ALLOCSTEP)) == NULL)
                        return NULL;

                // append word to ret
                strcat(ret, word);
                strcat(ret, " ");
                nRet += nWord + 1;

                nWord = 0;
            }
        }
        free(word);

        // remove trailing blank
        ret[strlen(ret) - 1] = '\0';
        return ret;
    }
    // in case of mem alloc failure
    return NULL;
}

.

revwords, .

- . i . line, .

inword. , . : IN OUT.

#define IN      0    /* inside a word */
#define OUT     1    /* outside a word */

nWord nallocWord word word. word - . , word , .

nRet nallocRet : ret , ret. ret - , , .

: , line NULL. , assert <assert.h>.

. , word ret, , , . .

if ((word = malloc(nallocWord = INITALLOC)) != NULL && 
                (ret = calloc(nallocRet = INITALLOC, sizeof(char))) != NULL) {

, , . AND INITALLOC word , NULL ( ). INITALLOC nallocWord, , , , word.

AND INITALLOC ret , NULL. INITALLOC nallocRet. , calloc malloc. , calloc zero , malloc . ret ; , .

#define INITALLOC 16   /* number of characters initially alloc'ed */
#define ALLOCSTEP 32   /* number of characters to increase by */

, , () .

if while, line . while .

  • (inword == OUT), (line[i]) - (.. ), inword IN. if,

  • (inword == IN), , word nWord. , word, . , NULL. , nallocWord ALLOCSTEP, .

  • (inword == IN && isspace(line[i]) (i == 0), inword OUT, null-terminate word, revword. - word ret. , . nRet + nWord > nallocRet , ret word nallocRet , ret. , . , NULL. i == 0, , , ret.

word ret strcat. , .

nRet ret. + 1 . nWord 0, word, .

, word, , ret. ret. , - . malloc/calloc free.

revword, .

char *revword(char *word)
{
    char *p, *q;

    assert(word != NULL);
    assert(*word != '\0');

    for (p = word, q = word + strlen(word) - 1; q > p; ++p, --q) {
        char tmp;

        tmp = *p;
        *p = *q;
        *q = tmp;
    }

    return word;
}

, p q. p word, q word. p q , q , p. , p q.

, word.

main, .

fgets(str, SIZE, stdin);
str[strlen(str) - 1] = '\0';

char *myrev(const char *line);

char *res = myrev(str);

printf("%s", res);
free(res);

for (i = 0; i < N; i++).

We must remove the trailing newline from the buffer strthat fgetsremains there. Then we declare the function myrevand then store the return value myrevin a temporary order so that we can use this pointer when we have freeit.

0
source

Source: https://habr.com/ru/post/1016374/


All Articles