-2

I had to define a Pascal style string as a structure and also define a C string, then to write a function to convert the C string "Mississippi" into a Pascal style string. Pascal style strings have member variables int with number of characters and char variable with string without '\0' at the end.

My problem is in for-loop function. How can I put chars from C string into a new defined Pascal style string ?

I am not allowed to use the string.h header file.

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

typedef struct PascalString {
  int size;
  char *string;
} PString;

struct PascalString *newPascalString(char *stringC) {  
  int i;  
  PString *pascal_string = malloc(sizeof(struct PascalString));  
  pascal_string->size = 11;
  pascal_string->string = malloc(sizeof(char) * pascal_string->size);

  for(i = 0; i < pascal_string->size; i++) {
    pascal_string[i] = stringC[i];  // here is my problem
  }  
  return pascal_string;
}

int main()
{ 
  char *c_string = "Mississippi";
  newPascalString(c_string);  
  return 0;
}
Dexterr
  • 19
  • 7
  • `strlen` is declared in the `string.h` header. – Iharob Al Asimi Dec 22 '14 at 12:08
  • 1
    `pascal_string[i] = stringC[i];` --> `pascal_string->string[i] = stringC[i];` – BLUEPIXY Dec 22 '14 at 12:11
  • Does your pascal string really consist of an `int` and a `char *` (i.e. a pointer to a string of characters), or does it (as I suspect) consist of an `int` followed directly by zero or more `char` elements, the number of which is determined by the `int`. You've done the former. Various (e.g. second answer at http://stackoverflow.com/questions/10925815/pascal-strings-in-c-sharp) suggest the latter. – abligh Dec 22 '14 at 12:47
  • Related: http://stackoverflow.com/questions/7648947/declaring-pascal-style-strings-in-c – abligh Dec 22 '14 at 12:48
  • Related: http://stackoverflow.com/questions/27575058/pascal-style-string-in-c-and-c-style-string-compare-in-one-function (not a dupe, but has a better `struct` definition) – abligh Dec 22 '14 at 12:51

2 Answers2

1

Just change this

for(i = 0; i < pascal_string->size; i++)

with

for(i = 0; (i < 11) && (stringC[i] != 0) ; i++)

since C strings are '\0' terminated, you have to loop untill you find the terminating '\0' or you are out of space.

You can also compute the length of the string like this

for (i = 0 ; stringC[i] != '\0' ; ++i)
    pascal_string->size++;

and then keep the loop as it was

for(i = 0; i < pascal_string->size; i++)

there is another issue with your code, this is worng

pascal_string[i] = stringC[i];

you should store the characters in the string member like this

pascal_string->string[i] = stringC[i];

Apparently you need this

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

typedef struct PascalString {
    int size;
    char *string;
} PString;

PString *newPascalString(char *stringC) {
    int i;

    PString *pascal_string = malloc(sizeof(struct PascalString));
    if (pascal_string == NULL) /* always check the return value of malloc */
        return NULL;

    pascal_string->size = 0;
    for (i = 0; stringC[i] != '\0'; ++i)
        ++pascal_string->size;

    pascal_string->string = malloc(pascal_string->size);
    if (pascal_string->string == NULL) {
        free(pascal_string);
        return NULL;
    }

    for(i = 0; i < pascal_string->size; i++)
        pascal_string->string[i] = stringC[i];  // here is my problem

    return pascal_string;
}

int main()
{
    char *c_string = "Mississippi";
    PString *pascal_string;

    pascal_string = newPascalString(c_string);
    if (pascal_string != NULL) {
        if (pascal_string->size == 11)
            printf("the pascal string has length 11 excluding the terminating `'\\0'`.\n");
        else
            printf("the pascal string length is not 11.\n");
        if (pascal_string->string != NULL) {
            /* write to standard output exacly pascal_string->size characters */
            /* printf will not work here, it needs `'\0'` at the end */
            fwrite(pascal_string->string, 1, pascal_string->size, stdout);
            printf("\n");
            /* free pascal_string->string, allocated with 
             *
             *     pascal_string->string = malloc(pascal_string->size) 
             */
            free(pascal_string->string);
        }
        /* free pascal_string, allocated with
         *
         *     pascal_string = malloc(sizeof(struct PascalString)) 
         */
        free(pascal_string);
    }
    /* since pascal_string == NULL no need to call free */
    return 0;
}
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • getting the length was not his main problem – Giorgi Moniava Dec 22 '14 at 12:10
  • @iharob, thanks a lot. I must accept such a style in for loop and other loops. – Dexterr Dec 22 '14 at 12:10
  • @iharob, yes, yes and yes. Thanks very much. ;) – Dexterr Dec 22 '14 at 14:13
  • @iharob, maybe you should put one more free(pascal_string); before return 0; out of if-control structure ? – Dexterr Dec 22 '14 at 14:36
  • @Dexterr Why do you think that is needed, it's not, but I would like to help clarify, so please tell me why did you think of that? – Iharob Al Asimi Dec 22 '14 at 14:38
  • @iharob, I am not sure, because I make always mistakes with malloc and free. I am not sure where to put free ? Thats a reason why I am asking ? – Dexterr Dec 22 '14 at 14:42
  • If you call `malloc` and it returns non-`NULL`, then you should call `free` when you no longer need the memory, if the condition above is false then `pascal_string == NULL`, and calling `free` with a `NULL` argument does nothing, you don't need to free anything because you didn't get any memory from `malloc`. – Iharob Al Asimi Dec 22 '14 at 15:00
  • @iharob, OK, but, "you didn't get any memory from malloc", yes but what about this: pascal_string->string = malloc(pascal_string->size); that makes me confused ? – Dexterr Dec 22 '14 at 15:13
  • It returns a pointer to a memory block which will hold, the string itself, there is a `free` for it in `main` this part `if (pascal_string->string == NULL) {free(pascal_string); return NULL;}`. – Iharob Al Asimi Dec 22 '14 at 15:15
  • @iharob, oohhhh I see. OK. Thanks a lot. One more question if you can add it to this code. If I need to make one more function which from two Pascal style strings "Tenne" and "ssee" make one Pascal style string "Tennessee". This function take two parameters, two pointers on string arrays of Pascal style strings and put those two strings together into one string and the function return a pointer with Pascal style string "Tennessee". – Dexterr Dec 22 '14 at 15:24
  • You have to ask a new question for that. Since if I add it to the code here it will make no sense, try writing something and when you get stuck, post a new question, I will gladly help you. – Iharob Al Asimi Dec 22 '14 at 15:26
1

To create the pascal-style string, You need to make some changes to your code.

As you mentioned, the problem is

pascal_string[i] = stringC[i];

pascal_string is a variable of type PString *. What you're trying to access is actually pascal_string->string[i].

Note: instead of using a hard-coded value of 11, you can determine the length of supplied string and allocate memory accordingly. [Equivalent of strlen()]

pascal_string->string = malloc((my_strlen(stringC)+1));              //allocate one more byte than supplied string size
if (pascal_string->string){                           //check malloc success.
    for(i = 0; (stringC[i] != 0); i++) {    //continue upto end of input string
        pascal_string->string[i] = string[i];  
    }  
    pascal_string->string[i] = 0;                                //terminating null
}
return pascal_string;                                //return

Pseudo-code for my_strlen():

int my_strlen(char * ip)
{
    int i = 0;
    for (i = 0; ip[i] != '\0'; i++);
    return i;
}
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • pascal_string->string = malloc((11+2)); This is wrong, because if I have C string with 11 chars that means that I have 12 bytes of space but in a new Pascal style string I need only space for 11 without '\0' – Dexterr Dec 22 '14 at 12:17
  • @iharob Happens a lot of time, with me also. Don't understand why the DV doesn't bother to leave a comment. – Sourav Ghosh Dec 22 '14 at 12:20
  • @Dexterr was updating my answer. Also , added check for `malloc()`. – Sourav Ghosh Dec 22 '14 at 12:20
  • @SouravGhosh, it should be: pascal_string->string = malloc(11), I don't understand why you need 1 more, 11+1 ? – Dexterr Dec 22 '14 at 12:23
  • @Dexterr `11+1`, in case the `size` value is supplied by calling `strlen()` or equivalent function. It doesn't count the terminating null for `size` value, but you'll need to one to terminate your string properly. – Sourav Ghosh Dec 22 '14 at 12:24