I'm new in C programming and I'm trying to make a function that sends what is stored in one array character that each time is going to change. So if my array is first "hello" it should send only 5 characters, but if later is "goodbye" it should send 7. What I want to avoid is have to write a lot of characters if I want to extend my array, like in this:
int say (buttonpressed){
char a[11] = {'h','e','l','l','o'};
int i;
for (i = 0;i<12;i++)
{
U2TXREG = a[i];
while(U2STAbits.TRMT==0);
}
buttonpressed = 0;
return 0;
}
I would apreciate any ideas, thanks!
You need to know the length of your array or use an End-Of-String character (which usually is \x0 - a binary zero).
int say (buttonpressed){
char* a = "hello";
int i;
int size=strlen(a);
for (i = 0;i<size;i++)
{ //rest as before
By using a string constant you initialize the array to end with a null (0) char. This can then be used to find the string length using strlen.
I have also just used a pointer to the string constant as you are not modifying it.
You really need to explain more what do you want to do.
From what you say I understand that you want to change the size and contents of your array without changing the for loop.
If that's the case you can use this:
#define ARRAY_LENGTH 12 /* 12 is an example */
int say (buttonpressed)
{
char a[ARRAY_LENGTH] = { . . . . };
int i;
for(i =0; i<ARRAY_LENGTH; i++){
...
}
....
}
I would store the data and the actual size in a struct (similiar to how you would use a std::vector in C++
struct vec{
char data[11];
unsigned int size;
}
Then in your for loop can just loop from i=0 to i
If your array is always going to be a string, a c-style string would be idiomatic in c. This is just an char array terminated by \0, and test for \0 while looping over the array.
Related
I want to preface my question by mentioning that I am a CS student that is very new to coding.
I am attempting to write a script that will add a set of array of characters to two arrays that are nested within a loop. The array of characters are prefixes for two courses, and I am using a function called "matcher" (that accepts an array that will hold a prefix, and an integer that holds the course number that we want to match to the corresponding prefix) within the loop.
The issue that I am facing is that when I run this, the first array(.prefix3) gets concatenated with the prefix for the second array(.prefix4), which seems to happen after the loop runs for a second time. I am unsure as to why this is occurring, specially since each array can only hold 7 characters. Here is the code, thank you all in advance:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char name[20];
int ID;
int number_of_courses;
int course_numbers[4];
char prefix1[7];
char prefix2[7];
char prefix3[7];
char prefix4[7];
int taken;
} student_info;
void matcher(char *,int );
int main()
{
student_info students[100];
int j=2;
int course_placeholder;
for(int i=0;i<2;i++)
{
printf("Enter course number %d:",i+1);//Type "9696" or "1232"
scanf("%d",&course_placeholder);
if(j==1)
{
matcher(students[0].prefix2,course_placeholder);
}
else if(j==2)
{
matcher(students[0].prefix3,course_placeholder);//this is concatenating the string for some reason. Trying to determine why.
}
else if(j==3)
{
matcher(students[0].prefix4,course_placeholder);
}
j++;
}
printf("%s\n%s\n",students[0].prefix3,students[0].prefix4);//students[0].prefix3 is concatenating for an unknown reason.
return 0;
}
void matcher(char *prefix_placeholder,int course_placeholder)
{
if(course_placeholder==9696)
{
strcpy(prefix_placeholder,"MAT 236");
}
else if(course_placeholder==1232)
{
strcpy(prefix_placeholder,"COP 220");
}
}
Although you cannot see it, string literals with 7 visible characters, such as this one:
"COP 220"
^ - NULL terminator is implied here
actually contain 8 characters, not 7. The last character is \0 ( AKA NULL )
So, when allocating memory in an array which is designed to contains C strings ( defined as a NULL terminated char array ) always include space enough for the NULL
char prefix1[8] = {0}; //1 extra element for NULL, all elements initialized to NULL
To test this yourself, do this:
size_t size = sizeof "MAT 236" ;//expect size == 8 (includes NULL)
int len = strlen("MAT 236");//expect len == 7 (does not include NULL)
The arrays
char prefix1[7];
char prefix2[7];
char prefix3[7];
char prefix4[7];
are too short to store 7-character strings like "MAT 236" and "COP 220" because they require at least 8-character arrays including terminating null-characters.
Allocate enough elements to avoid troubles.
I need to intialize an empty array of strings with fixed size ( 3 by 100 for example), pass it to a function to fill it with data and perform things like strcpy(), strcmp(), memset() on it. After the function is terminated I need to be able to read the data from my main().
What I tried so far:
char arrayofstrings[3][100] = {0};
char (*pointer)[3][100] = &arrayofstrings;
function(pointer);
Initalizing an (empty?) array of strings and initializing a pointer on the first element.
int function (char (*pointer)[3][100])
{
strcpy((*pointer)[i], somepointertostring);
strcmp((*pointer)[i], somepointertostring)
memset((*pointer)[i], 0, strlen((*pointer)[i]));
}
Is this a good way to do it? Is there an easier way to do it? Whats up with the brackets around the pointer?
C string functions expect a buffer to be null-terminated. Your arrayofstrings allocation happens on the stack. Depending on your compiler it might be initialized to all zeros or might contain garbage.
The simplest way in your case to make sure string functions won't overrun your buffers is to set the first character of each to 0 (null)
arrayofstrings[0][0] = 0x00;
arrayofstrings[1][0] = 0x00;
arrayofstrings[2][0] = 0x00;
This will give you 3, 100-char buffers that contain a valid empty "string". Note that you can only store 99 "characters" because the last character must be 0x00 (null-terminator).
char (*pointer)[3][100] = &arrayofstrings;
This is unnecessary.
Something to keep in mind about arrays in C is that the [] index is really only there to make things easier for the human programmer. Any array definition is simply a pointer to memory. The values inside the [][]...[] indexes and the type are used by the compiler to allocate the right amount of memory on the stack and do some simple math to come up with the right memory address for the element you want to access.
char arrayofstrings[3][100];
This will allocate sizeof(char)*3*100 bytes on the stack and give you a char* called 'arrayofstrings'. There's nothing special about the char* itself. It would be the same pointer if you had char arrayofstrings[300] or char arrayofstrings[3][10][10] or even long arrayofstrings[75] (char is 1 byte, long is 4 bytes).
Because you declared it as a multidimensional array with [a][b], when you ask for arrayofstrings[x][y], the compiler will calculate ((x*b)+y)*sizeof(type) and add it to the arrayofstrings pointer to get the address of the value you want. But because it's just a pointer, you can treat it like any other pointer and pass it around or cast it to other types of pointer or do pointer math with it.
You don't need the extra level of indirection.
An array, when passed to a function, is converted to a pointer to its first member. So if you declare the function like this:
int function(char (*pointer)[100])
Or equivalently:
int function(char pointer[][100])
Or:
int function(char pointer[3][100])
You can pass the array directly to the function:
function(arrayofstrings);
Then the body could look something like this:
strcpy(pointer[0], "some string");
strcpy(pointer[1], "some other string");
strcpy(pointer[2], "yet another string");
Best way to initialize an array of strings ...
char arrayofstrings[3][100] = {0}; is fine to initialize an array of strings.
In C, initialization is done only at object definition, like above.
Later code like strcpy(), assigns data to the array.
Best way to ... pass it to a function
When the C compiler supports variable length arrays, use function(size_t n, size_t sz, char a[n][sz]).
Add error checks.
Use size_t for array sizing and indexing.
#define somepointertostring "Hello World"
int function(size_t n, size_t sz, char arrayofstrings[n][sz]) {
if (sz <= strlen(somepointertostring)) {
return 1;
}
for (size_t i = 0; i < n; i++) {
strcpy(arrayofstrings[i], somepointertostring);
if (strcmp(arrayofstrings[i], somepointertostring)) {
return 1;
}
// Drop this it see something interesting in `foo()`
memset(arrayofstrings[i], 0, strlen(arrayofstrings[i]));
}
return 0;
}
void foo(void) {
char arrayofstrings[3][100] = {0};
size_t n = sizeof arrayofstrings / sizeof arrayofstrings[0];
size_t sz = sizeof arrayofstrings[0];
if (function(n, sz, arrayofstrings)) {
puts("Fail");
} else {
puts("Success");
puts(arrayofstrings[0]);
}
}
Initalizing an (empty?) array of strings and initializing a pointer on the first element.
The type of &arrayofstrings is char (*)[3][100] i.e. pointer to an object which is a 2D array of char type with dimension 3 x 100. So, this initialisation
char (*pointer)[3][100] = &arrayofstrings;
is not initialisation of pointer with first element of arrayofstrings array but pointer will point to whole 2D array arrayofstrings. That why, when accessing the elements using pointer you need bracket around it -
`(*pointer)[0]` -> first string
`(*pointer)[1]` -> second string and so on..
Is this a good way to do it? Is there an easier way to do it?
If you want pointer to first element of array arrayofstrings then you can do
char (*p)[100] = &arrayofstrings[0];
Or
char (*p)[100] = arrayofstrings;
both &arrayofstrings[0] and arrayofstrings are equivalent1).
Pass it to a function and access the array:
function() function signature should be -
int function (char (*pointer)[100])
// if you want the function should be aware of number of rows, add a parameter for it -
// int function (char (*pointer)[100], int rows)
this is equivalent to
int function (char pointer[][100])
and call it in from main() function like this -
function (p);
In the function() function you can access array as p[0], p[1] ...:
Sample program for demonstration:
#include <stdio.h>
#include <string.h>
#define ROW 3
#define COL 100
void function (char (*p)[COL]) {
strcpy (p[0], "string one");
strcpy (p[1], "string two");
strcpy (p[2], "string three");
}
int main(void) {
char arrayofstrings[ROW][COL] = {0};
char (*pointer)[COL] = &arrayofstrings[0];
function (pointer);
for (size_t i = 0; i < ROW; ++i) {
printf ("%s\n", arrayofstrings[i]);
}
return 0;
}
When you access an array, it is converted to a pointer to first element (there are few exceptions to this rule).
Ok so i am trying to write a function that checks whether or not a letter of a word exists within an array of strings(It does that for every letter in the word). After tinkering with it for a while, i figured that it crashed when it tried to use the strcmp(). I don't know what i am doing wrong since i just started learning C so any help would be appreciated. Here is the function:
char SingleChar(char *lex, int wordnum,char *word){
int i,j,k;
for(i=0;i<strlen(word);i++){
for(j=0;j<wordnum;j++){
for(k=0;k<strlen(lex[j]);k++){
if(strcmp(word[i],lex[k])){
return word[i];
}
}
}
}
return 0;
}
You have a misunderstanding about what char * means. It is a pointer to character. In C string are just a pointer to a character, flowed by other characters and a null terminator. What this means in your case, is that lex is a single string, not a list of strings.
ie
char *a = "imastring"; denotes that a is the address of a sequential piece of memory containing the characters [i][m][a][s][t][r][i][n][g][\0]. In C the null terminator is used to denote the end of a string.
What this means is that when you are calling strlen(lex[j]) you are just referencing a single character in lex and then reading to the end of the string, so your result will just decrease monotonically.
You probably want to do is use a double pointer. char ** list will point to an address, which points to an address referencing a block of sequential characters.
char ** list = (char **)malloc(sizeof(char *) * 5); would allocate you 5 sequential memory address which could then point to strings themselves. And you can assign them values as follows.
list[0] = a
I hope this helps.
Don't really see an array of strings... Your C file should look roughly like this:
#include <stdio.h>
char SingleChar(char *lex, int wordnum, char *word){"your function in here"};
int main(){
// Declare your variables here
// Call your function here SingleChar(params)
return 0;
}
To compare characters:
if(word[i]==lex[k]){
return word[i];
break;
}
Not quite sure what you are trying to do with your function other than that. You need to be more specific, I don't see your array of strings input.
In C there is no true string type. A string in C is just an array of characters.
An array of strings would be an array of pointers to an array of characters in memory.
If you wanted to check for a letter within an array of "strings".
You would want a pointer that moves through each letter of the array and compares each character.
The strcmp() function will return true (1) or false (0), depending on whether the strings are equal or not.
So what you'd want I think is for your program to compare the characters of your word with every other word in the array of strings.
This program goes through the entire word then tells you if the letter exists.
For each letter of whatever word you enter.
--
#include <stdio.h>
#include <string.h>
/*
Function to check for a letter of a word
in an array of strings */
void singleChar(char *word,int arrlength, char *strings[])
{
int length = 0;
length = strlen(word); /* Calculates the length of the string */
for(int y = 0; y < arrlength ; y++) /*Increments to the next word in the array */
{
for(int i=0; i <= length ; i++) /*increments to the next letter of the word you want to check */
{
for(int x=0; x < strlen(strings[y]) ; x++) /*Increments x based on the length of the string */
{
char *p = strings[y];
if(word[i] == p[x]) /*Compares the the first letter of both strings */
{
printf("The letter %c exists.\n", word[i]);
}
}
}
}
}
int main ( void )
{
/*Example */
char *p = "Hello";
char *a[2];
a[0]="Hello";
singleChar(p, 1,a);
}
An array of pointers to strings is provided as the input. The task is to reverse each string stored in the input array of pointers. I've made a function called reverseString() which reverses the string passed to it. This functions works correctly as far as i know.
The strings stored/referenced in the input array of pointers are sent one by one to the reverseString() function. But the code hangs at some point in the reverseString() function when the values of the passed string are swapped using a temp variable. I can't figure out why the code is hanging while swapping values. Please help me with this.
The code is as follows:
#include <stdio.h>
void reverseString(char*);
int main()
{ char *s[] = {"abcde", "12345", "65gb"};
int i=0;
for(i=0; i< (sizeof(s)/sizeof(s[0]) ); i++ )
{ reverseString(s[i]);
printf("\n%s\n", s[i]);
}
getch();
return 0;
}//end main
void reverseString(char *x)
{ int len = strlen(x)-1;
int i=0;
char temp;
while(i <= len-i)
{ temp = x[i];
x[i] = x[len-i];
x[len-i] = temp;
i++;
}
}//end reverseString
You are trying to change string literals.
String literals are usually not modifiable, and really should be declared as const.
const char *s[] = {"abcde", "12345", "65gb"};
/* pointers to string literals */
If you want to make an array of modifiable strings, try this:
char s[][24] = {"abcde", "12345", "65gb"};
/* non-readonly array initialized from string literals */
The compiler will automatically determine you need 3 strings, but it can't determine how long each needs to be. I've made them 24 bytes long.
The strings ("abcde" etc) could be stored in readonly memory. Anything is possible when you try to modify those strings, therefore. The pointers to the strings are modifiable; it is just the strings themselves that are not.
You should include <string.h> to obtain the declaration of strlen(3), and another header to obtain the function getch() - it is not in <stdio.h> on my MacOS X system (so I deleted the call; it is probably declared in either <stdio.h> or <conio.h> on Windows).
Hope this helps you! what i am doing here is that i am going to the address of the last character in the string then printing them all by decreasing the pointer by 1 unit (for character its 2 bytes(please check)).
//program to reverse the strings in an array of pointers
#include<stdio.h>
#include<string.h>
int main()
{
char *str[] = {
"to err is human....",
"But to really mess things up...",
"One needs to know C!!"
};
int i=0; //for different strings
char *p; //declaring a pointer whose value i will be setting to the last character in
//the respective string
while(i<3)
{
p=str[i]+strlen(str[i])-1;
while(*p!='\0')
{
printf("%c",*p);
p--;
}
printf("\n");
i++;
}
}
I am trying to create an array of strings in C. If I use this code:
char (*a[2])[14];
a[0]="blah";
a[1]="hmm";
gcc gives me "warning: assignment from incompatible pointer type". What is the correct way to do this?
edit: I am curious why this should give a compiler warning since if I do printf(a[1]);, it correctly prints "hmm".
If you don't want to change the strings, then you could simply do
const char *a[2];
a[0] = "blah";
a[1] = "hmm";
When you do it like this you will allocate an array of two pointers to const char. These pointers will then be set to the addresses of the static strings "blah" and "hmm".
If you do want to be able to change the actual string content, the you have to do something like
char a[2][14];
strcpy(a[0], "blah");
strcpy(a[1], "hmm");
This will allocate two consecutive arrays of 14 chars each, after which the content of the static strings will be copied into them.
There are several ways to create an array of strings in C. If all the strings are going to be the same length (or at least have the same maximum length), you simply declare a 2-d array of char and assign as necessary:
char strs[NUMBER_OF_STRINGS][STRING_LENGTH+1];
...
strcpy(strs[0], aString); // where aString is either an array or pointer to char
strcpy(strs[1], "foo");
You can add a list of initializers as well:
char strs[NUMBER_OF_STRINGS][STRING_LENGTH+1] = {"foo", "bar", "bletch", ...};
This assumes the size and number of strings in the initializer match up with your array dimensions. In this case, the contents of each string literal (which is itself a zero-terminated array of char) are copied to the memory allocated to strs. The problem with this approach is the possibility of internal fragmentation; if you have 99 strings that are 5 characters or less, but 1 string that's 20 characters long, 99 strings are going to have at least 15 unused characters; that's a waste of space.
Instead of using a 2-d array of char, you can store a 1-d array of pointers to char:
char *strs[NUMBER_OF_STRINGS];
Note that in this case, you've only allocated memory to hold the pointers to the strings; the memory for the strings themselves must be allocated elsewhere (either as static arrays or by using malloc() or calloc()). You can use the initializer list like the earlier example:
char *strs[NUMBER_OF_STRINGS] = {"foo", "bar", "bletch", ...};
Instead of copying the contents of the string constants, you're simply storing the pointers to them. Note that string constants may not be writable; you can reassign the pointer, like so:
strs[i] = "bar";
strs[i] = "foo";
But you may not be able to change the string's contents; i.e.,
strs[i] = "bar";
strcpy(strs[i], "foo");
may not be allowed.
You can use malloc() to dynamically allocate the buffer for each string and copy to that buffer:
strs[i] = malloc(strlen("foo") + 1);
strcpy(strs[i], "foo");
BTW,
char (*a[2])[14];
Declares a as a 2-element array of pointers to 14-element arrays of char.
Ack! Constant strings:
const char *strings[] = {"one","two","three"};
If I remember correctly.
Oh, and you want to use strcpy for assignment, not the = operator. strcpy_s is safer, but it's neither in C89 nor in C99 standards.
char arr[MAX_NUMBER_STRINGS][MAX_STRING_SIZE];
strcpy(arr[0], "blah");
Update: Thomas says strlcpy is the way to go.
Here are some of your options:
char a1[][14] = { "blah", "hmm" };
char* a2[] = { "blah", "hmm" };
char (*a3[])[] = { &"blah", &"hmm" }; // only since you brought up the syntax -
printf(a1[0]); // prints blah
printf(a2[0]); // prints blah
printf(*a3[0]); // prints blah
The advantage of a2 is that you can then do the following with string literals
a2[0] = "hmm";
a2[1] = "blah";
And for a3 you may do the following:
a3[0] = &"hmm";
a3[1] = &"blah";
For a1 you will have to use strcpy() (better yet strncpy()) even when assigning string literals. The reason is that a2, and a3 are arrays of pointers and you can make their elements (i.e. pointers) point to any storage, whereas a1 is an array of 'array of chars' and so each element is an array that "owns" its own storage (which means it gets destroyed when it goes out of scope) - you can only copy stuff into its storage.
This also brings us to the disadvantage of using a2 and a3 - since they point to static storage (where string literals are stored) the contents of which cannot be reliably changed (viz. undefined behavior), if you want to assign non-string literals to the elements of a2 or a3 - you will first have to dynamically allocate enough memory and then have their elements point to this memory, and then copy the characters into it - and then you have to be sure to deallocate the memory when done.
Bah - I miss C++ already ;)
p.s. Let me know if you need examples.
If you don't want to keep track of number of strings in array and want to iterate over them, just add NULL string in the end:
char *strings[]={ "one", "two", "three", NULL };
int i=0;
while(strings[i]) {
printf("%s\n", strings[i]);
//do something
i++;
};
Or you can declare a struct type, that contains a character arry(1 string), them create an array of the structs and thus a multi-element array
typedef struct name
{
char name[100]; // 100 character array
}name;
main()
{
name yourString[10]; // 10 strings
printf("Enter something\n:);
scanf("%s",yourString[0].name);
scanf("%s",yourString[1].name);
// maybe put a for loop and a few print ststements to simplify code
// this is just for example
}
One of the advantages of this over any other method is that this allows you to scan directly into the string without having to use strcpy;
If the strings are static, you're best off with:
const char *my_array[] = {"eenie","meenie","miney"};
While not part of basic ANSI C, chances are your environment supports the syntax. These strings are immutable (read-only), and thus in many environments use less overhead than dynamically building a string array.
For example in small micro-controller projects, this syntax uses program memory rather than (usually) more precious ram memory. AVR-C is an example environment supporting this syntax, but so do most of the other ones.
In ANSI C:
char* strings[3];
strings[0] = "foo";
strings[1] = "bar";
strings[2] = "baz";
The string literals are const char *s.
And your use of parenthesis is odd. You probably mean
const char *a[2] = {"blah", "hmm"};
which declares an array of two pointers to constant characters, and initializes them to point at two hardcoded string constants.
Your code is creating an array of function pointers. Try
char* a[size];
or
char a[size1][size2];
instead.
See wikibooks to arrays and pointers
hello you can try this bellow :
char arr[nb_of_string][max_string_length];
strcpy(arr[0], "word");
a nice example of using, array of strings in c if you want it
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]){
int i, j, k;
// to set you array
//const arr[nb_of_string][max_string_length]
char array[3][100];
char temp[100];
char word[100];
for (i = 0; i < 3; i++){
printf("type word %d : ",i+1);
scanf("%s", word);
strcpy(array[i], word);
}
for (k=0; k<3-1; k++){
for (i=0; i<3-1; i++)
{
for (j=0; j<strlen(array[i]); j++)
{
// if a letter ascii code is bigger we swap values
if (array[i][j] > array[i+1][j])
{
strcpy(temp, array[i+1]);
strcpy(array[i+1], array[i]);
strcpy(array[i], temp);
j = 999;
}
// if a letter ascii code is smaller we stop
if (array[i][j] < array[i+1][j])
{
j = 999;
}
}
}
}
for (i=0; i<3; i++)
{
printf("%s\n",array[i]);
}
return 0;
}
char name[10][10]
int i,j,n;//here "n" is number of enteries
printf("\nEnter size of array = ");
scanf("%d",&n);
for(i=0;i<n;i++)
{
for(j=0;j<1;j++)
{
printf("\nEnter name = ");
scanf("%s",&name[i]);
}
}
//printing the data
for(i=0;i<n;i++)
{
for(j=0;j<1;j++)
{
printf("%d\t|\t%s\t|\t%s",rollno[i][j],name[i],sex[i]);
}
printf("\n");
}
Here try this!!!
I was missing somehow more dynamic array of strings, where amount of strings could be varied depending on run-time selection, but otherwise strings should be fixed.
I've ended up of coding code snippet like this:
#define INIT_STRING_ARRAY(...) \
{ \
char* args[] = __VA_ARGS__; \
ev = args; \
count = _countof(args); \
}
void InitEnumIfAny(String& key, CMFCPropertyGridProperty* item)
{
USES_CONVERSION;
char** ev = nullptr;
int count = 0;
if( key.Compare("horizontal_alignment") )
INIT_STRING_ARRAY( { "top", "bottom" } )
if (key.Compare("boolean"))
INIT_STRING_ARRAY( { "yes", "no" } )
if( ev == nullptr )
return;
for( int i = 0; i < count; i++)
item->AddOption(A2T(ev[i]));
item->AllowEdit(FALSE);
}
char** ev picks up pointer to array strings, and count picks up amount of strings using _countof function. (Similar to sizeof(arr) / sizeof(arr[0])).
And there is extra Ansi to unicode conversion using A2T macro, but that might be optional for your case.
Each element is a pointer to its first character
const char *a[2] = {"blah", "hmm"};
A good way is to define a string your self.
#include <stdio.h>
typedef char string[]
int main() {
string test = "string";
return 0;
}
It's really that simple.