I found this example
int SizeofCharArray(char *phrase)
{
int size = 0;
int value = phrase[size];
while(value != 0)
{
value = phrase[size];
size++;
};
//printf("%i%s", size, "\n");
return size;
}
here
But how can I count number of letters in string array using pure C? Even I do not understand how can I initialize string array?!
Thank you!
The posted code is of rather poor quality. The name of the function, SizeofCharArray, does not match the description, count number of letters in string array.
If you want to return the number of characters in the array, use:
int SizeofCharArray(char *phrase)
{
int size = 0;
char* cp = phrase;
while( *cp != '\0')
{
size++;
cp++;
};
return size;
}
If you want to return the number of letters in the array, use:
int isLetter(char c)
{
return (( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ));
}
int GetNumberOfLetters(char *phrase)
{
int num = 0;
char* cp = phrase;
while( *cp != '\0')
{
if ( isLetter(*cp) )
{
num++;
}
cp++;
};
return num;
}
This will count the number of alphabetic characters in a c-string:
#include <ctype.h>
int numberOfLetters(char *s)
{
int n = 0;
while (*s)
if (isalpha(*s++))
n++;
return n;
}
If you want the actual number of characters, counting characters like spaces and numbers, just use strlen(s) located in string.h.
To find the length of C string, you can use strlen() function
#include<string.h>
char str[]="GJHKL";
const char *str1="hhkjj";
int len1=strlen(str)<<"\n";
int len2=strlen(str1);
It's not particularly good C. I doesn't give you the size of a char array -- that's impossible to determine if you've lost that information. What it does give you is the size of a null-terminated char array (AKA a c-string), and it does so by counting the characters until it finds the null-terminator (0 byte or '\n'). As a matter of fact, what you've got up top is a not particularly good strlen implementation (strlen is a standard library function that does the same thing -- determine the size of a null-terminated char array)
I believe this below should be a little more C-ish implementation of the same thing:
size_t strlen(const char *s){
const char* ptr = s;
for(; *ptr; ++ptr); //move the pointer until you get '\0'
return ptr-s; //return the difference from the original position (=string length;)
}
It returns size_t (64 bit unsigned int if you're on a 64 bit machine and 32 on 32 machines, so it will work on arbitrarily long strings as long as they fit into memory) and it also declares that it won't modify the array it measures (const char *s means a pointer you promise not to use to change what it points to).
Related
I am really new to C and in my first half year at university. This is my first questio on StackOverflow.
My task is to program it so every string stored in numbers is being converted into a decimal, without changing anything outside the main function.
I am now trying for the past 4 hours to solve this problem, where I want to iterate trough every char in the string I am currently to then, based on there position in comparison to the length to convert it into a decimal.
My only question here is to someone help me to understand how I can get the string length without using strlen() due to the fact I can't add #include <string.h>
This is what I got so far (getting the length of the array to iterate through every index):
#include <stdio.h>
#include <math.h> // Kompilieren mit -lm : gcc -Wall -std=c11 dateiname.c -lm
int main() {
char* numbers[] = {
"01001001",
"00101010",
"010100111001",
"011111110100101010010111",
"0001010110011010101111101111010101110110",
"01011100110000001101"};
// Add here..
int length = sizeof(numbers);
for ( int i = 0; i < length; i++ ){
//how do i get the string size without strlen() D:
}
return 0;
}
In C, strings are really just char arrays with a special terminator character to mark the end of the string. So, say you have something like:
char *str = "hello";
This is essentially equivalent to this:
char str[] = {'h', 'e', 'l', 'l', 'o', '\0'};
Notice that \0 character at the end of the array? This is the special terminator character that C places at the end of strings. Functions like strlen() pretty much iterate through the char array looking for the first occurrence of the \0 character and then stopping.
So, you can make your own version of strlen(), say my_strlen() like this:
int my_strlen(char *str)
{
/* Initialize len to 0 */
int len = 0;
/* Iterate through str, increment len, and stop when we reach '\0' */
while(str[len] != '\0')
len++;
/* Return the len */
return len;
}
Then within your for loop, you can just call this function. Also, note that your calculation of the size of the numbers array:
int length = sizeof(numbers);
will not give you the number of elements in the array. That code gives you the size (in bytes) or numbers which is an array of char pointers. If you want to get the number of elements, you have to divide that size by the size (in bytes) of a single element (i.e., a char pointer). So, something like this would work:
int length = sizeof(numbers) / sizeof(numbers[0]);
Your final code can look something like this:
#include <stdio.h>
#include <math.h> // Kompilieren mit -lm : gcc -Wall -std=c11 dateiname.c -lm
int my_strlen(char *str) {
/* Initialize len to 0 */
int len = 0;
/* Iterate through str, increment len, and stop when we reach '\0' */
while(str[len] != '\0')
len++;
/* Return the len */
return len;
}
int main() {
char* numbers[] = {
"01001001",
"00101010",
"010100111001",
"011111110100101010010111",
"0001010110011010101111101111010101110110",
"01011100110000001101"};
// Add here..
// Notice the change here
int length = sizeof(numbers) / sizeof(numbers[0]);
for(int i = 0; i < length; i++ ){
int str_len = my_strlen(numbers[i]);
// Do what you need with str_len
}
return 0;
}
This project can be done without computing the length of the strings. How? In C, all strings are nul-terminated containing the nul-character '\0' (with ASCII value 0) after the last character that makes up the string. When you need to iterate over a string, you just loop until the character values is 0 (e.g. the nul-character)
This is how all string function know when to stop reading characters. Since you have an array-of-pointers that contains your strings, you just need to loop over each pointer and for each pointer, loop over each character until the nul-character is found.
Putting it altogether, (and noting you don't need math.h), you can do:
#include <stdio.h>
#include <math.h> // Kompilieren mit -lm : gcc -Wall -std=c11 dateiname.c -lm
int main() {
char* numbers[] = {
"01001001",
"00101010",
"010100111001",
"011111110100101010010111",
"0001010110011010101111101111010101110110",
"01011100110000001101"};
int nnumbers = sizeof numbers / sizeof *numbers; /* no. of elements */
for (int i = 0; i < nnumbers; i++) {
long long unsigned number = 0;
/* you don't care about the length, strings are nul-terminated,
* just loop until \0 is found.
*/
for (int j = 0; numbers[i][j]; j++) {
number <<= 1; /* shift left */
number += numbers[i][j] == '1' ? 1 : 0; /* add bit */
}
printf ("%s = %llu\n", numbers[i], number); /* output result */
}
return 0;
}
(note: you must use a 64-bit type to hold the converted values as "1010110011010101111101111010101110110" requires a minimum of 38 bits to represent)
Example Use/Output
Simple example output converting each string to a numeric value:
$ ./bin/binstr2num
01001001 = 73
00101010 = 42
010100111001 = 1337
011111110100101010010111 = 8342167
0001010110011010101111101111010101110110 = 92790519158
01011100110000001101 = 379917
#include <stdio.h>
int main(){
char arr[20]="Hello";
int count=0;
while(arr[count]!='\0'){
count++;
}
printf("%d",count);
return 0;
}
Look at this small code, you will understand. In C a string ended with a NULL character. We can use that advantage.
There are a few ways to do it. IMO, a simple, reasonable way to implement strlen is:
size_t string_length(const char *s) { return strchr(s, '\0') - s; }
but if you're not allowed to use strlen then you're probably not allowed to use strchr either. So you just have to count. The most idiomatic way to do that is probably a bit obscure for a complete beginner, so here is a more verbose method.
Note that your computation of the number of elements in the array is invalid, and has been corrected below.
#include <stdio.h>
int
length(const char *s)
{
int len = 0;
while( *s++ ){
len += 1;
}
return len;
}
int
main(void)
{
char *numbers[] = {
"01001001",
"00101010",
"010100111001",
"011111110100101010010111",
"0001010110011010101111101111010101110110",
"01011100110000001101"
};
int count = sizeof numbers / sizeof *numbers; /* Number of entries */
for( int i = 0; i < count; i++ ){
printf(" length of %s is %d\n", numbers[i], length(numbers[i]));
}
return 0;
}
It's pretty subjective, but IMO a more idiomatic way to write this is:
#include <stdio.h>
int
length(const char *e)
{
const char *s = e;
while( *e++ )
;
return e - s - 1;
}
int
main(void)
{
char *numbers[] = {
"01001001",
"00101010",
"010100111001",
"011111110100101010010111",
"0001010110011010101111101111010101110110",
"01011100110000001101"
};
char **e = numbers + sizeof numbers / sizeof *numbers;
for( char **t = numbers; t < e; t++ ){
printf(" length of %s is %d\n", *t, length(*t));
}
return 0;
}
I am supposed to create a program, which creates an array with the abbreviation of an constant char Array. While my program does not return any errors, it also does not print any characters at my certain printf spots. Because of that I assume that my program does not work properly, and it isn't filling my array with any characters.
void abbrev(const char s[], char a[], size_t size) {
int i = 0;
while (*s != '\0') {
printf('%c', *s);
if (*s != ' ' && *s - 1 == ' ') {
a[i] = *s;
i++;
printf('%c', a[i]);
}
s++;
}
}
void main() {
char jordan1[60] = " Electronic Frontier Foundation ";
char a[5];
size_t size = 5;
abbrev(jordan1, a, size);
system("PAUSE");
}
The actual result is nothing. At least I assume so, since my console isn't showing anything. The result should be "EFF" and the size_t size is supposed to limit my char array a, in case the abbreviation is too long. So it should only implement the letters until my array is full and then the '\0', but I did not implement it yet, since my program is apparantly not filling the array at all.
#include <stdio.h>
#include <ctype.h>
/* in: the string to abbreviate
out: output abbreviation. Function assumes there's enough room */
void abbrev(const char in[], char out[])
{
const char *p;
int zbPosOut = 0; /* current zero-based position within the `out` array */
for (p = in; *p; ++p) { /* iterate through `in` until we see a zero terminator */
/* if the letter is uppercase
OR if (the letter is alphabetic AND we are not at the zero
position AND the previous char. is a space character) OR if the
letter is lowercase and it is the first char. of the array... */
if (isupper(*p) || (isalpha(*p) && (p - in) > 0 && isspace(p[-1]))
|| (islower(*p) && p == in)) {
out[zbPosOut++] = *p; /* ... then the letter is the start letter
of a word, so add it to our `out` array, and
increment the current `zbPosOut` */
}
}
out[zbPosOut] = 0; /* null-terminate the out array */
}
This code says a lot in few lines. Let's take a look:
isupper(*p) || (isalpha(*p) && (p - in) > 0 && isspace(p[-1]))
|| (islower(*p) && p == in)
If the current character (*p) is an uppercase character OR if it is alphabetc (isalpha(*p) and the previous character p[-1] is a space, then we may consider *p to be the first character of a word, and it should be added to our out array. We include the test (p - in) > 0 because if p == in, then we are at the zero position of the array and therefore p[-1] is undefined.
The order in this expression matters a lot. If we were to put (p - in) > 0 after the isspace(p[-1]) test, then we would not be taking advantage of the laziness of the && operator: as soon as it encounters a false operand, the following operand is not evaluated. This is important because if p - in == 0, then we do not want to evaluate the isspace(p[-1]) expression. The order in which we have written the tests makes sure that isspace(p[-1]) is evaluated after making sure we are not at the zero position.
The final expression (islower(*p) && p == in) handles the case where the first letter is lowercase.
out[zbPosOut++] = *p;
We append the character *p to the out array. The current position of out is kept track of by the zbPosOut variable, which is incremented afterwards (which is why we use postscript ++ rather than prefix).
Code to test the operation of abbrev:
int main()
{
char jordan1[] = " electronic frontier foundation ";
char out[16];
abbrev(jordan1, out);
puts(out);
return 0;
}
It gives eff as the output. For it to look like an acronym, we can change the code to append the letter *p to out to:
out[zbPosOut++] = toupper(*p);
which capitalizes each letter added to the out array (if *p is already uppercase, toupper just returns *p).
void print_without_duplicate_leading_trailing_spaces(const char *str)
{
while(*str == ' ' && *str) str++;
while(*str)
{
if(*str != ' ' || (*str == ' ' && *(str + 1) != ' ' && *str))
{
putchar(*str);
}
str++;
}
}
What you want to do could be simplified with a for() loop.
#include <stdio.h>
#include <string.h>
void abbrev(const char s[], char a[], size_t size) {
int pos = 0;
// Loop for every character in 's'.
for (int i = 0; i < strlen(s); i++)
// If the character just before was a space, and this character is not a
// space, and we are still in the size bounds (we subtract 1 for the
// terminator), then copy and append.
if (s[i] != ' ' && s[i - 1] == ' ' && pos < size - 1)
a[pos++] = s[i];
printf("%s\n", a); // Print.
}
void main() {
char jordan1[] = " Electronic Frontier Foundation ";
char a[5];
size_t size = 5;
abbrev(jordan1, a, size);
}
However, I don't think this is the best way to achieve what you are trying to do. Firstly, char s[0] cannot be gotten due to the check on the previous character. Which brings me to the second reason: On the first index you will be checking s[-1] which probably isn't a good idea. If I were implementing this function I would do this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void abbrev(const char s[], char a[], size_t size) {
char *str = strdup(s); // Make local copy.
size_t i = 0;
// Break it up into words, then grab the first character of each word.
for (char *w = strdup(strtok(str, " ")); w != NULL; w = strtok(NULL, " "))
if (i < size - 1)
a[i++] = w[0];
free(str); // Release our local copy.
printf("%s\n", a);
}
int main() {
char jordan1[] = "Electronic Frontier Foundation ";
char a[5];
size_t size = 5;
abbrev(jordan1, a, size);
return 0;
}
I tried to write a function to convert a string to an int:
int convert(char *str, int *n){
int i;
if (str == NULL) return 0;
for (i = 0; i < strlen(str); i++)
if ((isdigit(*(str+i))) == 0) return 0;
*n = *str;
return 1;
}
So what's wrong with my code?
*n = *str means:
Set the 4 bytes of memory that n points to, to the 1 byte of memory that str points to. This is perfectly fine but it's probably not your intention.
Why are you trying to convert a char* to an int* in the first place? If you literally just need to do a conversion and make the compiler happy, you can just do int *foo = (int*)bar where bar is the char*.
Sorry, I don't have the reputation to make this a comment.
The function definitely does not perform as intended.
Here are some issues:
you should include <ctype.h> for isdigit() to be properly defined.
isdigit(*(str+i)) has undefined behavior if str contains negative char values. You should cast the argument:
isdigit((unsigned char)str[i])
the function returns 0 if there is any non digit character in the string. What about "-1" and "+2"? atoi and strtol are more lenient with non digit characters, they skip initial white space, process an optional sign and subsequent digits, stopping at the first non digit.
the test for (i = 0; i < strlen(str); i++) is very inefficient: strlen may be invoked for each character in the string, with O(N2) time complexity. Use this instead:
for (i = 0; str[i] != '\0'; i++)
*n = *str does not convert the number represented by the digits in str, it merely stores the value of the first character into n, for example '0' will convert to 48 on ASCII systems. You should instead process every digit in the string, multiplying the value converted so far by 10 and adding the value represented by the digit with str[i] - '0'.
Here is a corrected version with your restrictive semantics:
int convert(const char *str, int *n) {
int value = 0;
if (str == NULL)
return 0;
while (*str) {
if (isdigit((unsigned char)*str)) {
value = value * 10 + *str++ - '0';
} else {
return 0;
}
}
*n = value;
return 1;
}
conversion of char* pointer to int*
#include
main()
{
char c ,*cc;
int i, *ii;
float f,*ff;
c = 'A'; /* ascii value of A gets
stored in c */
i=25;
f=3.14;
cc =&c;
ii=&i;
ff=&f;
printf("\n Address contained
in cc =%u",cc);
printf("\n Address contained
in ii =%u",ii);
printf(:\n Address contained
in ff=%u",ff);
printf(\n value of c= %c",
*cc);
printf(\n value of i=%d",
**ii);
printf(\n value of f=%f",
**ff);
}
I have made up a function which returns some chars , all I want to do is to append all those returned chars into one string .
#include <stdio.h>
#include <string.h>
char func(int n);
int main()
{
int i;
char str[] = "";
size_t p = strlen(str);
for (i =0 ; i < 5; i++){
str[p++] = func(i);
str[p] = '\0';
p++;
}
printf("%s",str);
return 0;
}
char func(int n){
if (n == 0)
return '1';
if (n == 1)
return '2';
if (n > 1)
return '3';
}
//EDIT Output for this is 19
char func(n){
if (n == 0)
return '1';
if (n == 1)
return '2';
if (n > 1)
return '3';
}
You should always specify the type for variables.
Please use something like int n instead of just n.
It's also bad that all of your returns are conditional, it's better to have a return statement that's guaranteed to be executed no matter what *:
char func(int n) {
if (n == 0) return '1';
if (n == 1) return '2';
return '3';
}
* Because not returning a value from a function that should return a value is undefined behaviour.
Now that we have that out of the way, let's have a look at your main():
int main() {
int i;
char str[] = "";
size_t p = strlen(str);
for (i =0 ; i < 5; i++){
str[p++] = func(i);
str[p] = '\0';
p++;
}
printf("%s",str);
return 0;
}
str[] is not big enough to store all the characters you write to it, resulting in undefined behaviour.
Your loop body is written in a weird way, why are you incrementing p twice?
Here a very simple program that writes 5 characters into str:
#include <stdio.h>
char func(int n) {
if (n == 0) return '1';
if (n == 1) return '2';
return '3';
}
int main() {
int i;
// Allocate 6 bytes (5 characters) on the stack
char str[6] = "";
for (i = 0 ; i < 5; i++) {
str[i] = func(i);
}
// Strings *must* be NULL terminated in C
str[5] = 0;
printf("%s",str);
return 0;
}
The size of your str here is "0" (0 using the strlen and 1 using the sizeof operator because it counts the '\0' caracter) so you can not add more element to the str, and if you try, the program will crash. So you have two possibilies here, the first is to declare a fixed table size and the number n will be limited by the size, the second is a dynamic one using mallic. To intialize it to zeros you can just use the memset API.
Well short answer is everything you did would be right if you have in the array enough memory to hold those 5 characters and the \0 if you want to treat it as a string (NUL terminated char array).
"" is a string literal containing only the \0. Length of this string is 0. What about the array? Applying sizeof over it reveals that it is capable of holding one character. (Well it contained \0).
Now with your code you surely did access positions that are beyond the size of the array. This is undefined behavior - mentioned by the C standard.
Solution is to either have an array having size capable of holding the maximum character you would like to store someday. Or you can have a char* to which you can assign address of allocated chunk by using functions like malloc,realloc etc. Benefit of this, you can increase memory as much as you need on runtime depending on the number of characters you want to store.
I have a variable length string where each character represents a hex digit. I could iterate through the characters and use a case statement to convert it to hex but I feel like there has to be a standard library function that will handle this. Is there any such thing?
Example of what I want to do. "17bf59c" -> int intarray[7] = { 1, 7, 0xb, 0xf, 5, 9, 0xc}
No, there's no such function, probably because (and now I'm guessing, I'm not a C standard library architect by a long stretch) it's something that's quite easy to put together from existing functions. Here's one way of doing it decently:
int * string_to_int_array(const char *string, size_t length)
{
int *out = malloc(length * sizeof *out);
if(out != NULL)
{
size_t i;
for(i = 0; i < length; i++)
{
const char here = tolower(string[i]);
out[i] = (here <= '9') ? (here - '\0') : (10 + (here - 'a'));
}
}
return out;
}
Note: the above is untested.
Also note things that maybe aren't obvious, but still subtly important (in my opinion):
Use const for pointer arguments that are treated as "read only" by the function.
Don't repeat the type that out is pointing at, use sizeof *out.
Don't cast the return value of malloc() in C.
Check that malloc() succeeded before using the memory.
Don't hard-code ASCII values, use character constants.
The above still assumes an encoding where 'a'..'f' are contigous, and would likely break on e.g. EBCDIC. You get what you pay for, sometimes. :)
using strtol
void to_int_array (int *dst, const char *hexs)
{
char buf[2] = {0};
char c;
while ((c = *hexs++)) {
buf[0] = c;
*dst++ = strtol(buf,NULL,16);
}
}
Here's another version that allows you to pass in the output array. Most of the time, you don't need to malloc, and that's expensive. A stack variable is typically fine, and you know the output is never going to be bigger than your input. You can still pass in an allocated array, if it's too big, or you need to pass it back up.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* str of length len is parsed to individual ints into output
* length of output needs to be at least len.
* returns number of parsed elements. Maybe shorter if there
* are invalid characters in str.
*/
int string_to_array(const char *str, int *output)
{
int *out = output;
for (; *str; str++) {
if (isxdigit(*str & 0xff)) {
char ch = tolower(*str & 0xff);
*out++ = (ch >= 'a' && ch <= 'z') ? ch - 'a' + 10 : ch - '0';
}
}
return out - output;
}
int main(void)
{
int values[10];
int len = string_to_array("17bzzf59c", values);
int i = 0;
for (i = 0; i < len; i++)
printf("%x ", values[i]);
printf("\n");
return EXIT_SUCCESS;
}
#include <stdio.h>
int main(){
char data[] = "17bf59c";
const int len = sizeof(data)/sizeof(char)-1;
int i,value[sizeof(data)/sizeof(char)-1];
for(i=0;i<len;++i)
sscanf(data+i, "%1x",value + i);
for(i=0;i<len;++i)
printf("0x%x\n", value[i]);
return 0;
}