2

I am writing a C-code to use in PIC 18 micro-controller using MPLAB IDE. I have 5 strings and I want to be able to use pointers. The idea is having an array containing the pointers to the string arrays. and have them print on the console. The code below compiles with No errors or warnings, but all I get on the console is garbage.

Can someone point me to the right direction. many thanks. sorry if my formatting of the code is not right.

#include <stdio.h>
#include <p18f4520.h>
#include <stdlib.h> 
#pragma config WDT = OFF

#define size 64

#pragma romdata s1=0x300                        //specific ROM addresses for the data
  rom char *s1[] = "Hello";
#pragma romdata s2 = 0x307
  rom char *s2 = "Welcome to C programming";

#pragma romdata s3=0x31A
  rom char *s3= "My name is ";  

#pragma romdata s4=0x32C
  rom char *s4 = "Pic18 program";

#pragma romdata s5=0x33A
  rom char *s5 ="Goodbye, I hope this works!";


void printString(const char*);

void main (void) 
{   
    int i=0;

    char stringArray [] = {*s1, *s2, *s3, *s4, *s5};
    char *ptr=stringArray;


       while(i<5)
        {
             printString(&ptr[i]);
             i++;
          }
}

void printString( const char *strPtr)
{
   while(*strPtr !='\0')
     {
       printf("%c", strPtr);
       strPtr++;

      } 
}

`

Stkabi
  • 121
  • 2
  • 3
  • 8
  • 3
    You really should consider getting a better compiler. `char *s1[] = ...` are declared as arrays of pointers. You take the contents of them `{*s1, *s2,...`, ie arrays, and stuff them inside an array of chars. At a minimum, you should have gotten errors/warnings "can not convert char* to char", "implicit typecast to a narrow type" or similar. GCC gives the following. Error: Invalid initializer. Warning: initializer element is not computable at load time. Warning: initialization makes integer from pointer without a cast. – Lundin Nov 02 '11 at 07:37
  • @Lundin: I agree with you for the compiler being buggy. as a matter of fact it wouldn't let me declare the arrays like usual in the beginning, but it took it afterwards. Unfortunately I have to use it for Assembly, so I can trace the program through, and verify the data and its location addresses. – Stkabi Nov 02 '11 at 08:53
  • You will have to read up in detail about those compiler-specific #pragmas and the rom keyword. Perhaps there is a different syntax when declaring arrays, I have no idea. – Lundin Nov 02 '11 at 09:34
  • I would expect code to be `rom char s1[] = "Hello";` and `char *stringArray [] = {s1, ...` – chux - Reinstate Monica Aug 11 '15 at 21:22
  • `"Welcome to C programming"` is longer than the distance between `0x307` and `0x31A`. You could try increasing these numbers so that the strings do not overlap. In theory it'd be nice if the linker detected this for you but sometimes they don't. – M.M Dec 15 '15 at 13:01

4 Answers4

1

Well This is the answer.

#include <stdio.h>
#include <p18f4520.h>
#include <stdlib.h> 
#include <string.h>
#pragma config WDT = OFF

#pragma romdata s1=0x300                      //specific ROM addresses for the data
 rom char s1[] = "Hello";
#pragma romdata s2 =0x307
   rom char s2[] = "Welcome to C programming";
#pragma romdata s3=0x41A
   rom char s3[] = "My name is";
#pragma romdata s4=0x32C
  rom char s4[] = "Pic18 program";
#pragma romdata s5=0x33A
   rom char s5[] ="Goodbye, I hope this works!";

void printAndCount(rom char *strPtr);
int j=0; int i=0;
void main (void)
{
    rom char* stringArray [] = {s1, s2, s3, s4, s5};
                    while(i<5 )
                {
                    printAndCount(stringArray[i]);  
                            i++;
                }
}
void printAndCount(rom char *strPtr)
    {   
    while (*strPtr != '\0' )
        {   printf("%c", *strPtr);
            strPtr++;
            ++j;    
                }
            printf("     %d\n",j);
            j=0;
}
Stkabi
  • 121
  • 2
  • 3
  • 8
0

The problem is that in your code, stringArray stands for a memory block that stores the first character of each string, not the address of them, try this:

void main (void) 
{   
    int i=0;

    char * stringArray [] = {s1, s2, s3, s4, s5};
    char **ptr=stringArray;


       while(i<5)
        {
             printString(*ptr[i]);
             i++;
          }
}
wangshuaijie
  • 1,821
  • 3
  • 21
  • 37
  • 1
    Change `printString(*ptr[i])` to `printString(ptr[i])` and in printString() change `printf("%c", strPtr);` to `printf("%c", *strPtr);` – Alexey Frunze Nov 02 '11 at 07:15
  • @Alex, sorry my typo, it is printString(ptr[i]); , not printString(*ptr[i]); – wangshuaijie Nov 02 '11 at 07:17
  • Oh, overlooked one point, since the type of s1 is char *[], stringArray should be declared this way: char * stringArray [] = {s1[0], s2, s3, s4, s5}; – wangshuaijie Nov 02 '11 at 07:21
  • -1 That is far from the only error in the code. The ROM data isn't allocated properly, the syntax is wrong. Everything should be declared const, including that those pointers (pointer-to-const). Also, printString must be changed accordingly, as already pointed out. This answer is not complete. – Lundin Nov 02 '11 at 07:27
0

There are several fundamental errors in that code. Use this one instead.

#include <stdio.h>
#include <p18f4520.h>
#include <stdlib.h> 
#pragma config WDT = OFF

#define size 64

// store ARRAYS here not pointers!
// Im not sure what non-standard "rom" means more exactly, 
// but these should be const in the C language
#pragma romdata s1=0x300                        //specific ROM addresses for the data
  rom const char s1[] = "Hello";                      
#pragma romdata s2 = 0x307
  rom const char s2[] = "Welcome to C programming";   

#pragma romdata s3=0x31A
  rom const char s3[] = "My name is ";                

#pragma romdata s4=0x32C
  rom const char s4[] = "Pic18 program";

#pragma romdata s5=0x33A
  rom const char s5[] ="Goodbye, I hope this works!";


void printString (const char* strPtr);

void main (void) 
{   
    int i=0;

    // this, however, must be an array of pointers (that point to the strings)
    // since the strings are const, the pointers must be declared pointer-to-const:
    const char* stringArray [] = {s1, s2, s3, s4, s5};

    while(i<5)
    {
         printString(stringArray[i]);  // now this syntax suddenly turned sane
         i++;
    }
}

void printString (const char *strPtr)
{
   while(*strPtr !='\0')
     {
       printf("%c", *strPtr);
       strPtr++;
      } 
}
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • @Lundin: I have tried the code I am getting an error "type qualifier mismatch in assignment". I think it is so because I need to pass the arrays into main (), but it needs to be a "void main(void)" – Stkabi Nov 02 '11 at 08:48
  • @Lundin: I used %s with the code corrections, it works in a different compiler but not in the PIC18 MPLAB IDE (from Microchip). – Stkabi Nov 02 '11 at 09:17
  • @wallyk Ah yeah, it needs to be *strPtr. Fixed, thanks for pointing that out. – Lundin Nov 02 '11 at 09:29
  • @Stkabi = Where do you get that error? If it is during the allocation of the strings, it likely has something to do with "rom" and "const" being in conflict with each other. I have no idea what "rom" does in detail, it isn't a valid C keyword. – Lundin Nov 02 '11 at 09:31
  • 1
    Perhaps the rom keyword acts as part of the type. Maybe it requires the declaration to be `rom const char* stringArray` or some such. I can tell you for certain that the error has _nothing_ to do with the declaration of main or the place where the arrays are declared. They are declared at file scope (global) so they are visible inside main(). – Lundin Nov 02 '11 at 09:38
  • @Lundin: I removed the Rom and it is working now. this is what I found out: 'rom' is not another datatype, but a storage location qualifier. Usually constants are stored in rom to save ram space and to prevent accidental modification of the variable. You can store any data type( int, char....) in rom. – Stkabi Nov 02 '11 at 09:55
  • @Stkabi Yes but these _should_ be stored in ROM, unless your intention is to modify the strings in runtime. If you need to modify them they obviously needs to be in RAM and they can't be const. – Lundin Nov 02 '11 at 09:58
-1

Try this instead:

#include <stdio.h>
#include <p18f4520.h>
#include <stdlib.h> 
#pragma config WDT = OFF

#pragma romdata s1=0x300                        //specific ROM addresses for the data
  rom char s1[] = "Hello";
#pragma romdata s2 = 0x307
  rom char s2[] = "Welcome to C programming";
#pragma romdata s3=0x31A
  rom char s3[] = "My name is ";  
#pragma romdata s4=0x32C
  rom char s4[] = "Pic18 program";
#pragma romdata s5=0x33A
  rom char s5[] ="Goodbye, I hope this works!";


void main (void) 
{   
    int i;
    char *stringArray [] = {s1, s2, s3, s4, s5};

    for (i = 0;  i < 5;  ++i)
    {
        printf("%s", stringArray[i]);
    }
}

It simplifies and makes several fixes, the most significant to fix the problem was eliminating the * before each string name in stringArray. Other changes are made to be customary C coding.

wallyk
  • 56,922
  • 16
  • 83
  • 148
  • Change `char stringArray [] = {s1, s2, s3, s4, s5};` to `char* stringArray [] = {s1, s2, s3, s4, s5};`. – Alexey Frunze Nov 02 '11 at 07:13
  • This is about as buggy as the original post. Judging by the addresses, the OP obviously meant to store the whole strings at specific locations in ROM. You are only storing pointers at those locations. – Lundin Nov 02 '11 at 07:15
  • @Lundin: yep, you were right. I corrected them; 1 of 5 were right before, now all 5 are. – wallyk Nov 02 '11 at 07:19
  • Whether the rom keyword has an implicit const in it or not, I don't know. But had this been C language, the arrays would also have to be declared as const or the code/linking wouldn't behave as expected. stringArray needs to be an array of pointers to const. – Lundin Nov 02 '11 at 07:28
  • Trying this with a few modification to the string ROM addresses, I got a whole bunch of ))))))) on the console. – Stkabi Nov 02 '11 at 07:47