I am having trouble concatenating strings in C without library function.
I tried the following:
#include <stdio.h>
struct word {
char *str;
int wordSize;
};
void concat(struct word words[], int arraySize, int maxSize) { // word array, its size, and max size given
char result[maxSize];
int resultSize = 0;
struct word tmp;
for (int i = 0; i < arraySize; i++) {
tmp = words[i];
for (int j = 0; j < words[i].wordSize; j++, resultSize++) {
result[resultSize + j] = tmp.str[j];
}
}
puts(result);
}
For example, if the struct array words contain [{"he", 2}, {"ll", 2}, {"o", 1}], the result should be hello. However, this code prints h�l�o where the second and fourth letters are questionmark. Can anyone help me debug this?
Keep it simple and the bugs will fix themselves. Don't mix up the position in the result buffer with the loop iterators. No need for temporary variables.
#include <stdio.h>
typedef struct {
char *str;
int wordSize;
} word;
void concat(word words[], int arraySize, int maxSize) {
char result[maxSize];
int count=0;
for(int i=0; i<arraySize; i++)
{
for(int j=0; j<words[i].wordSize; j++)
{
result[count]= words[i].str[j];
count++;
}
}
result[count] = '\0';
puts(result);
}
int main()
{
word w[3] = { {"he", 2}, {"ll", 2}, {"o", 1} };
concat(w, 3, 128);
}
In this for loop
for (int j = 0; j < words[i].wordSize; j++, resultSize++) {
result[resultSize + j] = tmp.str[j];
}
you are incrementing resultSize and j simultaneously while you need to increase only the variable j and after the loop increase the variable resultSize by j.
But in any case the function is wrong because there is no check that resultSize is less than maxSize.
And moreover the built string is not appended with the terminating zero '\0'. As a result this statement
puts(result);
invokes undefined behavior.
There is no need to create the variable length array
char result[maxSize];
just to output the concatenated string.
The function can be declared and defined the following way as it is shown in the demonstrative program below.
#include <stdio.h>
struct word {
char *str;
int wordSize;
};
void concat( const struct word words[], size_t arraySize, size_t maxSize )
{
for ( size_t i = 0, j = 0; i < maxSize && j < arraySize; j++ )
{
for ( size_t k = 0; i < maxSize && k < words[j].wordSize; i++, k++ )
{
putchar( words[j].str[k] );
}
}
putchar( '\n' );
}
int main(void)
{
struct word words[] =
{
{ "he", 2 }, { "ll", 2 }, { "o", 1 }
};
const size_t arraySize = sizeof( words ) / sizeof( *words );
concat( words, arraySize, 5 );
return 0;
}
The program output is
hello
You have a couple of problems here. result[resultSize + j] means you are effectively skipping over half the characters in result. Secondly, if you copy the entire string, including the null character, puts will stop printing the result string at the end of the first word itself. So you need to skip copying the string terminator and put it in at the end of your whole concatenated string.
#include <stdio.h>
struct word {
char *str;
int wordSize;
};
void concat(struct word words[], int maxSize) { // word array and max size given
char result[maxSize];
int resultSize = 0;
struct word tmp;
for (int i = 0; i < 3; i++) {
tmp = words[i];
// Keep copying the words to result, one after the other
// But drop the last NULL character
for (int j = 0; j < (words[i].wordSize - 1); j++, resultSize++) {
result[resultSize] = tmp.str[j];
}
}
// Put the NULL character in after all words have been copied
result[resultSize] = 0;
puts(result);
}
struct word mywords[] =
{
{ "TestWord", sizeof("TestWord")},
{ "TestWord2", sizeof("TestWord2")}
};
int main(void)
{
concat(mywords, 100);
return 0;
}
Related
The problem: After the convert_tolower(words) function is completed I want to add a new word in the words array( if the words array has less than 5 words)..But I am getting either errors or unexpected results(e.g some weird characters being printed)...What i thought is shifting the elements of the words array and then work with pointers because I am dealing with strings.But I am having quite some trouble achieving that..Probably the problem is in lines
35-37
How I want the program to behave:
Get 5 words(strings) at most from user input
Take these strings and place them in an array words
Convert the elements of the array to lowercase letters
After the above,ask the user again to enter a new word and pick the position of that word.If the words array already has 5 words then the new word is not added.Else,the new word is added in the position the user chose.(The other words are not deleted,they are just 'shifted').
Also by words[1] I refer to the first word of the words array in its entirety
The code:
#include <stdio.h>
#include <string.h>
#define W 5
#define N 10
void convert_tolower(char matrix[W][N]);
int main() {
int j = 0;
int i = 0;
int len = 0;
char words[W][N] = {{}};
char test[W][N];
char endword[N] = "end";
char newword[N];
int position;
while (scanf("%9s", test), strcmp(test, endword)) {
strcpy(words[i++], test);
j++;
len++;
if (j == W) {
break;
}
}
convert_tolower(words);
printf("Add a new word\n");
scanf("%9s", newword);
printf("\nPick the position\n");
scanf("%d",position);
if (len < W) {
for (i = 0; i < W-1; i++) {
strcpy(words[i], words[i + 1]); /*Shift the words */
words[position] = newword;
}
}
for (i = 0; i < W; i++) {
printf("%s", words[i]);
printf("\n");
}
printf("End of program");
return 0;
}
void convert_tolower(char matrix[W][N]) {
int i;
int j;
for (i = 0; i < W; i++) {
for (j = 0; j < N; j++) {
matrix[i][j] = tolower(matrix[i][j]);
}
}
}
This initialization
char words[W][N] = {{}};
is incorrect in C. If you want to zero initialize the array then just write for example
char words[W][N] = { 0 };
In the condition of the while loop
while (scanf("%9s", test), strcmp(test, endword)) {
there is used the comma operator. Moreover you are using incorrectly the two-dimensional array test instead of a one-dimensional array
It seems you mean
char test[N];
//...
while ( scanf("%9s", test) == 1 && strcmp(test, endword) != 0 ) {
And there are used redundantly too many variables like i, j and len.
The loop could be written simpler like
char test[N];
//...
for ( ; len < W && scanf("%9s", test) == 1 && strcmp(test, endword) != 0; ++len )
{
strcpy(words[len], test);
}
In this call
scanf("%d",position);
there is a typo. You must to write
scanf("%d", &position);
Also you should check whether the entered value of position is in the range [0, len].
For example
position = -1;
printf("\nPick the position\n");
scanf("%d", &position);
if ( len < W && -1 < position && position <= len ) {
Also this for loop
for (i = 0; i < W-1; i++) {
strcpy(words[i], words[i + 1]); /*Shift the words */
words[position] = newword;
}
does not make a sense. And moreover this assignment statement
words[position] = newword;
is invalid. Arrays do not have the assignment operator.
You need to move all strings starting from the specified position to the right.
For example
for ( i = len; i != position; --i )
{
strcpy( words[i], words[i-1] );
}
strcpy( words[position], newword );
++len;
And it seems the function convert_tolower should be called for the result array after inserting a new word. And moreover you need to pass the number of actual words in the array.
convert_tolower(words, len);
The nested loops within the function convert_tolower should look at least the following way
void convert_tolower(char matrix[][N], int n) {
int i;
int j;
for (i = 0; i < n; i++) {
for (j = 0; matrix[i][j] != '\0'; j++) {
matrix[i][j] = tolower(( unsigned char )matrix[i][j]);
}
}
}
The main problem with your code was initially that you declared char *words[W][N], then tried to insert strings into this 2d array of pointers. Sparse use of organizing functions, and variables with large scopes than necessary made it hard to read. I think the best way to help you is to show you a working minimal implementation. Step 4 is not sufficiently specified. insert currently shift. It is not clear what should happen if you insert at position after empty slots, or if insert a position before empty slots and in particular if there are non-empty slots after said position.
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#define W 5
#define N 10
void convert(size_t w, size_t n, char list[][n]) {
for(size_t i = 0; i < w; i++) {
for(size_t j = 0; j < n; j++) {
list[i][j] = tolower(list[i][j]);
}
}
}
void insert(size_t w, size_t n, char list[][n], size_t pos, char *word) {
// out out of bounds
if(pos + 1 > w) return;
// shift pos through w - 2 pos
for(size_t i = w - 2; i >= pos; i--) {
strcpy(list[i + 1], list[i]);
if(!i) break;
}
// insert word at pos
strcpy(list[pos], word);
}
void print(size_t w, size_t n, char list[][n]) {
for (size_t i = 0; i < w; i++) {
printf("%u: %s\n", i, list[i]);
}
}
int main() {
char words[W][N] = { "a", "BB", "c" };
convert(W, N, words);
insert(W, N, words, 0, "start");
insert(W, N, words, 2, "mid");
insert(W, N, words, 4, "end");
insert(W, N, words, 5, "error")
print(W, N, words);
return 0;
}
and the output (note: "c" was shifted out as we initially had 3 elements and added 3 new words with valid positions):
0: start
1: a
2: mid
3: bb
4: end
I need help to understand an issue with my C code. I am trying to find longest substring within a given string without character repetition. When run on the leetcode platform, the code below gives me an error for the String "amqpcsrumjjufpu":
Runtime Error Message: Line 17: index -3 out of bounds for type 'int [256]'
However, the same code works fine when I run it from my computer or any online editor. Please help me to understand this behaviour difference.
#include <stdio.h>
#include <string.h>
int lengthOfLongestSubstring(char* s) {
char *h = s;
int A[256] = {0};
int length = 0;
int temp = 0;
int max = 0;
int len = strlen(s);
for(int i = 0; i < len;i ++){
int A[256] = {0};
length = 0;
h = s + i;
for(int j = i; j < len-1; j++){
if (A[h[j]] == 1) {
break;
} else {
A[h[j]] = 1;
length +=1;
}
if (max < length) {
max = length;
}
}
}
return max;
}
int main() {
char *s = "amqpcsrumjjufpu";
int ret = lengthOfLongestSubstring(s);
printf("SAURABH: %d",ret);
}
It seems you are trying to write a function that finds the length of the longest substring of unique characters.
For starters the function should be declared like
size_t lengthOfLongestSubstring( const char *s );
^^^^^^ ^^^^^
These declarations in the outer scope of the function
int A[256] = {0};
//...
int temp = 0;
are redundant. The variables are not used in the function.
The type char can behave either as the type signed char or the type unsigned char. So in expressions like this A[h[j]] you have to cast explicitly the character used as index to the type unsigned char as for example
A[( unsigned char )h[j]]
The inner loop
for(int j=i;j<len-1;j++){
will not execute for strings that contain only one character. So it does not make sense as it is written.
This if statement
if (max < length) {
max = length ;
}
needs to be placed outside the inner loop.
The algorithm used by you can be implemented the following way
#include <stdio.h>
#include <limits.h>
size_t lengthOfLongestSubstring(const char *s)
{
size_t longest = 0;
for (; *s; ++s )
{
size_t n = 0;
unsigned char letters[UCHAR_MAX] = { 0 };
for ( const char *p = s; *p && !letters[(unsigned char)*p - 1]++; ++p) ++n;
if (longest < n) longest = n;
}
return longest;
}
int main( void )
{
char *s = "123145";
printf("The longest substring has %zu characters.\n",
lengthOfLongestSubstring(s));
return 0;
}
The program output is
The longest substring has 5 characters.
Your code crashed because you read data out of range, suppose your input string is amqpcsrumjjufpu its length is 15, in outer loop for i = 13 you do assigment
h = s + i; // h was updated to indicate to 13th element of s
and in inner loop for first iteration, you read this element (j == i == 13)
A[h[j]]
so, you try to read this element A[*(h+j)], but h indicates to 13th element of s, and now you try to add 13 to this value, you want to read 26th position of s, you are out of range of s string.
Thanks Everyone for responses. While Vlad's code worked for all the test cases, here is my code that also passed all the test cases after changes suggested by Vlad and rafix.
int lengthOfLongestSubstring(char* s) {
char *h = s;
int max = 0;
int len = strlen(s);
if (len == 1) {
return 1;
}
for(int i = 0; i < len;i ++){
int A[256] = {0};
int length = 0;
for(int j = i; j < len; j++){
if (A[(unsigned char)h[j]] == 1) {
break;
} else {
A[(unsigned char) h[j]] = 1;
length +=1;
}
}
if (max < length) {
max = length;
}
}
return max;
}
Given an array of character strings such as...
char *example[] = {"s", "ss", "sss"};
How can I write a function to count the total number of chars in the array including the terminating characters, without using the standard library for strlen() etc.
Follows is my attempt
int countChars(char *array[], int len)
{
int total = 0, count = 0;
for (int i = 0; i < len; i++)
{
if (array[i] != NULL)
{
while (*array[i] != '\0') {
count++;
}
count++;
}
total += count;
}
return total;
}
An explanation on how char *array[] actually works for access wold be appreciated. I believe that it is supposed to be an array of pointers to strings.
You have to increment the index to consider each of the character.
Something like this:-
for (int i = 0; i < len; i++)
{
if (array[i] != NULL)
{
int j=0,count=0;
while (array[i][j++] != '\0') {
count++;
}
total += count;
}
}
Also reset the count or add to total at the end of all the calculation.
As an answer to your second question:-
char* array[] is basically denoting an array pointers each pointing
to the string literals with which you initialized it.
So once you use array[i] you should now think that it is nothing
other than a pointer to a string literal.
You need to reinitialize the variable count inside the for loop for each processed string and to increase the expression *array[i] inside the while loop.
Also it is better when the function has the return type size_t (size_t is the type that is returned by the standard C function strlen and by the operator sizeof)
The function can look as it is shown in the demonstrative program.
#include <stdio.h>
size_t countChars( const char *array[], size_t n )
{
size_t count = 0;
while ( n-- )
{
if ( array[n] )
{
size_t i = 0;
do { ++count; } while ( array[n][i++] );
}
}
return count;
}
int main(void)
{
const char * example[] = { "s", "ss", "sss" };
printf( "%zu\n", countChars( example, sizeof( example ) / sizeof( *example ) ) );
return 0;
}
The program output is
9
Each element of this array
char *example[] = {"s", "ss", "sss"};
has type char * and is a pointer to the first character of the corresponding string literal.
Since your array contains string constants you should declare it with const:
const char *example[3];
Without const the compiler will not warn you if you try to assign a character to example[i][j]. For the same reason the formal parameter should also be declared with const.
For a pure function with no side effects it is better to name it so that it reflects the result. Therefor I would use charCount instead of countChars (or maybe totalLength). The focus should be on a noun (namely count or length).
Here is my solution:
#include <stdio.h>
#define LEN(a) (sizeof (a) / sizeof (a)[0])
static int CharCount(const char *strings[], int len)
{
int result, i, j;
result = 0;
for (i = 0; i < len; i++) {
j = 0;
while (strings[i][j] != '\0') {
result++;
j++;
}
}
return result;
}
int main(void)
{
const char *strings[] = { "s", "ss", "sss" };
printf("character count: %d\n", CharCount(strings, LEN(strings)));
}
The length macro LEN is very convenient and is the least error prone way to handle array lengths.
Yes char *array[] = {"aa", "bb", "cc"} is an array of pointers to strings.
array[0] points to "aa"
array[1] points to "bb"
array[2] points to "cc"
You probably want this:
int countChars(char *array[], int len)
{
int count = 0;
for (int arrayindex = 0; arrayindex < len; arrayindex++)
{
const char *stringptr = array[arrayindex];
// stringptr will point successively
// to "s", to "ss" and to "sss"
while (*stringptr++)
count++; // increment count until NUL character encountered
count++; // one more for NUL character
}
return count;
}
int main() {
char *example[] = { "s", "ss", "sss" };
int x = countChars(example, 3); // x contains 9 after the call to countChars
// that is 2 + 3 + 4
}
Instead of hard coding 3 you could use sizeof(example) / sizeof(example[0]).
I have the following code:
#include "stdafx.h"
#include "string.h"
#include "ctype.h"
/*selection sort*/
void swap(int A[], int j, int k)
{
int p = A[k];
int i;
for (i = 0; i < (k - j); i++)
{
A[k - i] = A[k - i - 1];
}
A[j] = p;
}
/*greatest number in an array*/
int max(int A[], int N, int k)
{
int max = k, i;
for (i = k; i < N; i++)
{
if (A[max] < A[i])
max = i;
}
return max;
}
int count_nonspace(const char* str)
{
int count = 0;
while(*str)
{
if(!isspace(*str++))
count++;
}
return count;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[256];
int i = 0, j = 0, count[256] = { 0 };
char string[100] = "Hello world";
for (i = 0; i < 100; i++)
{
for (j = 0; j<256; j++)
{
if (tolower(string[i]) == (j))
{
count[j]++;
}
}
}
for (j = 0; j<256; j++)
{
printf("\n%c -> %d \n", j, count[j]);
}
}
Program is calculating the number of apperances of each character in a string. Now it prints the number of apperances of all 256 characters, whereas i want it to prinf only the character with greatest number of apperances in a string. My idea was to use the selection sort method to the array with the nubmer of apperances, but this is not working, thus my question is how to printf only the character with the greatest number of apperances in the string?
If anybody would have doubts, this is NOT my homework question.
EDIT: I've just noticed that this code printf apperances of characters begining with "j" why is that?
I started typing this before the others showed up, so I'll post it anyway. This is probably nearly the most efficient (increasing efficiency would add some clutter) way of getting an answer, but it doesn't include code to ignore spaces, count characters without regard to case, etc (easy modifications).
most_frequent(const char * str)
{
unsigned counts[256];
unsigned char * cur;
unsigned pos, max;
/* set all counts to zero */
memset(counts, 0, sizeof(counts));
/* count occurences of each character */
for (cur = (unsigned char *)str; *cur; ++cur)
++counts[*cur];
/* find most frequent character */
for (max = 0, pos = 1; pos < 256; ++pos)
if ( counts[pos] > counts[max] )
max = pos;
printf("Character %c occurs %u times.\n", max, counts[max]);
}
Create an array with your char as index.
Keep incrementing the value in the array based on the characters read.
Now get the max out of the array which gives you the most occurring char in your input.
Code will look like:
#include <stdio.h>
#include<string.h>
#include<stdlib.h>
int main(void) {
char buf[100];
int i=0,max =0,t=0;
int a[256];
memset(a,0,sizeof(a));
fgets(buf,100,stdin);
buf[strlen(buf)-1] = '\0';
while(buf[i] != '\0')
{
a[(int)buf[i]]++;
i++;
}
i=0;
for(i=0;i<256;i++)
{
if(a[i] > max)
{
max = a[i];
t = i;
}
}
printf("The most occurring character is %c: Times: %d",t,max);
return 0;
}
Here is a solution for that, based on your own solution, and using qsort().
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
struct Frequency
{
int character;
int count;
};
int compare(const void *const lhs, const void *const rhs)
{
return ((struct Frequency *)rhs)->count - ((struct Frequency *)lhs)->count;
}
int main(int argc, char* argv[])
{
int i = 0, j = 0;
struct Frequency count[256];
memset(&count, 0, sizeof(count));
char string[100] = "Hello world";
for (i = 0 ; i < 100 ; i++)
{
for (j = 0 ; j < 256 ; j++)
{
count[j].character = j;
if (tolower(string[i]) == j)
{
count[j].count += 1;
}
}
}
qsort(count, sizeof(count) / sizeof(*count), sizeof(*count), compare);
/* skip the '\0' which was counted many times */
if (isprint(count[1].character))
printf("\nThe most popular character is: %c\n", count[1].character);
else
printf("\nThe most popular character is: \\%03x\n", count[1].character);
for (j = 0 ; j < 256 ; j++)
{
if (isprint(count[j].character))
printf("\n%c -> %d \n", count[j].character, count[j].count);
else
printf("\n\\%03x -> %d \n", count[j].character, count[j].count);
}
}
notice that the '\0' is set for all the remainig bytes in
char string[100] = "Hello world";
so the count of '\0' will be the highest.
You could use strlen() to skip '\0', in the counting loop, but don't
for (i = 0 ; i < strlen(string) ; ++i) ...
do it this way
size_t length = strlen(string);
for (i = 0 ; i < length ; ++i) ...
Suppose that we have a string "11222222345646". So how to print out subsequence 222222 in C.
I have a function here, but I think something incorrect. Can someone correct it for me?
int *longestsubstring(int a[], int n, int *length)
{
int location = 0;
length = 0;
int i, j;
for (i = 0, j = 0; i <= n-1, j < i; i++, j++)
{
if (a[i] != a[j])
{
if (i - j >= *length)
{
*length = i - j;
location = j;
}
j = i;
}
}
return &a[location];
}
Sorry,I don't really understand your question.
I just have a little code,and it can print the longest sub string,hope it can help.
/*breif : print the longest sub string*/
void printLongestSubString(const char * str,int length)
{
if(length <= 0)
return;
int i ;
int num1 = 0,num2 = 0;
int location = 0;
for(i = 0; i< length - 1; ++i)
{
if(str[i] == str[i+1])
++num2;//count the sub string ,may be not the longest,but we should try.
else
{
if(num2 >num1)//I use num1 store the sum longest of current sub string.
{ num1 = num2;location = i - num2;}
else
;//do nothing for short sub string.
num2 = 0;
}
}
for(i = location;str[i]== str[num1];++i)
printf("%c",str[i]);
printf("\n");
}
int main()
{
char * str = "1122222234566";
printLongestSubString(str,13);
return 0;
}
From your code it appears you want to return the longest sub-sequence (sub-string). Since I'm relearning C I thought I would give it a shot.
I've used strndup to extract the substring. I'm not sure how portable it is but I found an implementation if needed, just click on the link. It will allocate memory to store the new cstring so you have to remember to free the memory once finished with the substring. Following your argument list, the length of the sub-string is returned as the third argument of the extraction routine.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *extract_longest_subsequence(const char *str, size_t str_len, size_t *longest_len);
int main()
{
char str[] = "11222234555555564666666";
size_t substr_len = 0;
char *substr = extract_longest_subsequence(str, sizeof(str), &substr_len);
if (!substr)
{
printf("Error: NULL sub-string returned\n");
return 1;
}
printf("original string: %s, length: %zu\n", str, sizeof(str)-1);
printf("Longest sub-string: %s, length: %zu\n", substr, substr_len);
/* Have to remember to free the memory allocated by strndup */
free(substr);
return 0;
}
char *extract_longest_subsequence(const char *str, size_t str_len, size_t *longest_len)
{
if (str == NULL || str_len < 1 || longest_len == NULL)
return NULL;
size_t longest_start = 0;
*longest_len = 0;
size_t curr_len = 1;
size_t i = 0;
for (i = 1; i < str_len; ++i)
{
if (str[i-1] == str[i])
{
++curr_len;
}
else
{
if (curr_len > *longest_len)
{
longest_start = i - curr_len;
*longest_len = curr_len;
}
curr_len = 1;
}
}
/* strndup allocates memory for storing the substring */
return strndup(str + longest_start, *longest_len);
}
It looks like in your loop that j is supposed to be storing where the current "substring" starts, and i is the index of the character that you are currently looking at. In that case, you want to change
for (i = 0, j = 0; i <= n-1, j < i; i++, j++)
to
for (i = 0, j = 0; i <= n-1; i++)
That way, you are using i to store which character you're looking at, and the j = i line will "reset" which string of characters you are checking the length of.
Also, a few other things:
1) length = 0 should be *length = 0. You probably don't actually want to set the pointer to point to address 0x0.
2) That last line would return where your "largest substring" starts, but it doesn't truncate where the characters start to change (i.e. the resulting string isn't necessarily *length long). It can be intentional depending on use case, but figured I'd mention it in case it saves some grief.