Load numbers from input into array - c

I have given input which contains data that I am going to process and saved into an array. The input looks like this :
{ [1, 10], [2,1] , [-10, 20] }
it can have more elements in it. I need to process it that I can load all numbers from [ number , number ] into 2d array , first number should be at 0th and second number should be at 1st index so this array should look like
[[1,10],[2,1],[-10,20]]
But I've failed to find the solution, how to process this input into my desired array. What is the right way to do it?
I tried to do as following:
int main()
{
long long int cisla[10][2];
int x;
int y;
int i;
int index=0;
int counter=0;
char c;
char zatvorka_one;
char zatvorka_three;
char ciarka;
char ciarka_two;
printf("Pozicia nepriatela\n");
c=getchar();
if(c!='{'){
return 0;
}
scanf(" %c%d,%d%c",&ciarka,&x,&y,&zatvorka_one);
cisla[index][0]=x;
cisla[index][1]=y;
index++;
while(1){
scanf("%c",&ciarka);
if(ciarka=='}'){
break;
}
scanf(" %c%d%,%d%c",&ciarka,&x,&y,&zatvorka_one);
cisla[index][0]=x;
cisla[index][1]=y;
index++;
}
for ( i = 0; i < index; i++){
printf("%d %d\n",cisla[i][0],cisla[i][1]);
}
}
But somehow it returns unexpected result, how can i fix it?

You should use gets instead of scanf. gets will return the entire string wich will be easear. Then you ahould read about strtok wich can be used to separate a string. For example: strtok(s,",") will separate your string into smaller strings. For the input {[12,4], [8,9]} will divide into: first string: {[12 second string: 4] third string [8 and fourth string 9]}. Now you will just have to remove the characters that are not numbers like { } and []. After that you will have strings only with the numbers so you can use another predefined fuction you should read abput called atoi. It recieves a string and turns it into an int (ascci to int). There is also an atof (ascci to float) if you need it. Tuturialpoints is a good place to look for examples on how to use these functions i mentioned.

I'm relatively new to C and SO. Maybe I shouldn't give you the solution, but I did. It follows the advice of sharp c student.
You could try to do it like this:
#include "stdafx.h"
#include "string.h"
#include "stdlib.h"
#define MAXNBRELM 10 // maximum number of elements; adjust as needed
int main()
{
int IntArr[MAXNBRELM][2]; // integer array to hold results
int s = 0; // subscript
int NbrElm; // number of elements found
char Buf[81]; // buffer to hold input
char * StrPtr; // pointer to string for fgets
char * TknChr; // each individual token
char * NxtTkn; // next token position (only needed for Visual C++)
StrPtr = fgets(Buf, 80, stdin);
TknChr = strtok_s(Buf, " {[,]}", &NxtTkn);
while (s <= MAXNBRELM && TknChr != NULL) {
IntArr[s][0] = atoi(TknChr);
TknChr = strtok_s(NULL, " {[,]}", &NxtTkn);
if (TknChr != NULL) {
IntArr[s][1] = atoi(TknChr);
TknChr = strtok_s(NULL, " {[,]}", &NxtTkn);
s++;
}
}
NbrElm = s;
for (s = 0; s < NbrElm; s++)
printf("%d %d\n", IntArr[s][0], IntArr[s][1]);
return 0;
}
This is for Visual Studio, is why I needed to use strtok_s and &NxtTkn.

Related

Shuffle words from a 1D array

I've been given this sentence and I need to shuffle the words of it:
char array[] = "today it is going to be a beautiful day.";
A correct output would be: "going it beautiful day is a be to today"
I've tried many things like turning it into a 2D array and shuffling the rows, but I can't get it to work.
Your instinct of creating a 2D array is solid. However in C that's more involved than you might expect:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
int main()
{
char array[] = "today it is going to be a beautiful day.";
char out_array[sizeof(array)];
char words[sizeof(array)][46];
int word_count = 0;
int letter_count = 0;
int on_word = 0;
int count = 0;
int i = 0;
int j = 0;
srand(time(NULL));
// parse words into 2D array
for (i = 0; i < sizeof(array); i++) {
if (array[i] == ' ') {
if (on_word) {
words[word_count++][letter_count] = '\0';
letter_count = 0;
on_word = 0;
}
} else if (array[i] == '\0' || array[i] == '.') {
break;
} else {
on_word = 1;
words[word_count][letter_count++] = array[i];
}
}
words[word_count++][letter_count] = '\0';
// randomly swap around words
for (i = 0; i < word_count; i++) {
char temp[46];
int idx = rand() % word_count;
if (idx != i) {
strcpy(temp, words[idx]);
strcpy(words[idx], words[i]);
strcpy(words[i], temp);
}
}
// output words into out_array
for (i = 0; i < word_count; i++) {
for (j = 0; words[i][j] != '\0'; j++) {
out_array[count++] = words[i][j];
}
out_array[count++] = ' ';
}
out_array[count - 1] = '\0';
printf("%s", out_array);
return 0;
}
You need two basic algorithms to solve this problem.
Split the input string into a list of words.
Randomly sample your list of words until there are no more.
1. Split the input string into a list of words.
This is much simpler than you may think. You don’t need to actually copy any words, just find where each one begins in your input string.
today it is going to be a beautiful day.
^---- ^- ^- ^---- ^- ^- ^ ^-------- ^--
There are all kinds of ways you can store that information, but the two most useful would be either an array of integer indices or an array of pointers.
For your example sentence, the following would be a list of indices:
0, 6, 9, 12, 18, 21, 24, 26, 36
To do this, just create an array with a reasonable upper limit on words:
int words[100]; // I wanna use a list of index values
int nwords = 0;
 
char * words[100]; // I wanna use a list of pointers
int nwords = 0;
If you do it yourself either structure is just as easy.
If you use strtok life is much easier with a list of pointers.
All you need at this point is a loop over your input to find the words and populate your list. Remember, a words is any alphabetic or numeric value (and maybe hyphens, if you want to go that far). Everything else is not a word. If you #include <ctype.h> you get a very handy function for classifying a character is “word” or “not-word”:
if (isalnum( input[n] )) its_a_word_character;
else its_not_a_word_character_meaning_we_have_found_the_end_of_the_word;
Now that you have a list of words, you can:
2. Randomly sample your list of words until there are no more.
There are, again, a number of ways you could do this. Already suggested above is to randomly shuffle the list of words (array of indices or array of pointers), and then simply rebuild the sentence by taking the words in order.
→ Beware, Etian’s example is not a correct shuffle, though it would probably go unnoticed or ignored by everyone at your level of instruction as it will appear to work just fine. Google around “coding horror fisher yates” for more.
The other way would be to just select and remove a random word from your array until there are no words left.
The random sampling is not difficult, but it does require some precise thinking, making this the actually most difficult part of your project.
To start you first need to get a proper random number. There is a trick to this that people are generally not taught. Here you go:
int random( int N ) // Return an UNBIASED pseudorandom value in [0, N-1].
{
int max_value = (RAND_MAX / N) * N;
int result;
do result = rand(); while (result >= max_value);
return result % N;
}
And in main() the very first thing you should do is initialize the random number generator:
#include <stdlib.h>
#include <time.h>
int main()
{
srand( (unsigned)time( NULL ) );
Now you can sample / shuffle your array properly. You can google "Fisher-Yates Shuffle" (or follow the link in the comment below your question). Or you can just select the next word:
while (nwords)
{
int index = random( nwords );
// do something with word[index] here //
// Remove the word we just printed from our list of words
// • Do you see what trick we use to remove the word?
// • Do you also know why this does not affect our random selection?
words[index] = words[--nwords];
}
Hopefully you can see that both of these methods are essentially the same thing. Whichever you choose is up to you. I personally would use the latter because of the following consideration:
Output
You can create a new string and then print it, or you can just print each word directly. As the homework (as you presented it) does not require generation of a new string, I would just print the output directly. This makes life simpler in the sense that you do not have to mess with another string array.
As you print each word (or append it to a new string), remember how you separated them to begin with. If you use strtok you can just use something like:
printf( "%s", words[index] ); // print word directly to stdout
 
strcat( output, words[index] ); // append word to output string
If you found the beginnings of each word yourself, you will have to again loop until you find the end of the word:
// Print word, character by character, directly to stdout
for (int n = index; isalnum( words[index+n] ); n++)
{
putchar( words[index+n] );
}
 
// Append word, character by character, to output string
for (int n = index; isalnum( words[index+n] ); n++)
{
char * p = strchr( output, '\0' ); // (Find end of output[])
*p++ = words[index+n]; // (Add char)
*p = '\0'; // (Add null terminator)
}
All that’s left is to pay attention to spaces and periods in your output.
Hopefully this should be enough to get you started.

First Not Repeating Character Code

Here is the question:
Write a solution that only iterates over the string once and uses O(1) additional memory, since this is what you would be asked to do during a real interview.
Given a string s, find and return the first instance of a non-repeating character in it. If there is no such character, return '_'.
And here is my code:
char firstNotRepeatingCharacter(char * s) {
int count;
for (int i=0;i<strlen(s);i++){
count=0;
char temp=s[i];
s[i]="_";
char *find= strchr(s,temp);
s[i]=temp;
if (find!=NULL) count++;
else return s[i];
}
if (count!=0) return '_';
}
I dont know what's wrong but when given an input:
s: "abcdefghijklmnopqrstuvwxyziflskecznslkjfabe"
the output is for my code is "g" instead of "d".
I thought the code should have escaped the loop and return "d" soon as "d" was found.
Thx in advance!!!
In your program, problem is in this statement-
s[i]="_";
You are assigning a string to a character type variable s[i]. Change it to -
s[i]='_';
At the bottom of your firstNotRepeatingCharacter() function, the return statement is under the if condition and compiler must be giving a warning for this as the function is supposed to return a char. Moreover, count variable is not needed. You could do something like:
char firstNotRepeatingCharacter(char * s) {
for (int i=0;i<strlen(s);i++){
char temp=s[i];
s[i]='_';
char *find= strchr(s,temp);
s[i]=temp;
if (find==NULL)
return s[i];
}
return '_';
}
But this code is using strchr inside the loop which iterates over the string so, this is not the exact solution of your problem as you have a condition that - the program should iterates over the string once only. You need to reconsider the solution for the problem.
May you use recursion to achieve your goal, something like - iterate the string using recursion and, somehow, identify the repetitive characters and while the stack winding up identify the first instance of a non-repeating character in the string. It's implementation -
#include <stdio.h>
int ascii_arr[256] = {0};
char firstNotRepeatingCharacter(char * s) {
char result = '-';
if (*s == '\0')
return result;
ascii_arr[*s] += 1;
result = firstNotRepeatingCharacter(s+1);
if (ascii_arr[*s] == 1)
result = *s;
return result;
}
int main()
{
char a[] = "abcdefghijklmnopqrstuvwxyziflskecznslkjfabe";
printf ("First non repeating character: %c\n", firstNotRepeatingCharacter(a));
return 0;
}
In the above code, firstNotRepeatingCharacter() function iterates over the string only once using recursion and during winding up of the stack it identifies the first non-repetitive character. I am using a global int array ascii_arr of length 256 to keep the track of non-repetitive character.
Java Solution:
Time Complexity: O(n)
Space Complexity: with constant space as it will only use more 26 elements array to maintain count of chars in the input
Using Java inbuilt utilities : but for inbuilt utilities time complexity is more than O(n)
char solution(String s) {
char[] c = s.toCharArray();
for (int i = 0; i < s.length(); i++) {
if (s.indexOf(c[i]) == s.lastIndexOf(c[i]))
return c[i];
}
return '_';
}
Using simple arrays. O(n)
char solution(String s) {
// maintain count of the chars in a constant space
int[] base = new int[26];
// convert string to char array
char[] input = s.toCharArray();
// linear loop to get count of all
for(int i=0; i< input.length; i++){
int index = input[i] - 'a';
base[index]++;
}
// just find first element in the input that is not repeated.
for(int j=0; j<input.length; j++){
int inputIndex = input[j]-'a';
if(base[inputIndex]==1){
System.out.println(j);
return input[j];
}
}
return '_';
}

Pointers to string C

trying to write function that returns 1 if every letter in “word” appears in “s”.
for example:

containsLetters1("this_is_a_long_string","gas") returns 1
containsLetters1("this_is_a_longstring","gaz") returns 0
containsLetters1("hello","p") returns 0
Can't understand why its not right:
#include <stdio.h>
#include <string.h>
#define MAX_STRING 100
int containsLetters1(char *s, char *word)
{
int j,i, flag;
long len;
len=strlen(word);
for (i=0; i<=len; i++) {
flag=0;
for (j=0; j<MAX_STRING; j++) {
if (word==s) {
flag=1;
word++;
s++;
break;
}
s++;
}
if (flag==0) {
break;
}
}
return flag;
}
int main() {
char string1[MAX_STRING] , string2[MAX_STRING] ;
printf("Enter 2 strings for containsLetters1\n");
scanf ("%s %s", string1, string2);
printf("Return value from containsLetters1 is: %d\n",containsLetters1(string1,string2));
return 0;
Try these:
for (i=0; i < len; i++)... (use < instead of <=, since otherwise you would take one additional character);
if (word==s) should be if (*word==*s) (you compare characters stored at the pointed locations, not pointers);
Pointer s advances, but it should get back to the start of the word s, after reaching its end, i.e. s -= len after the for (j=...);
s++ after word++ is not needed, you advance the pointer by the same amount, whether or not you found a match;
flag should be initialized with 1 when declared.
Ah, that should be if(*word == *s) you need to use the indirection operator. Also as hackss said, the flag = 0; must be outside the first for() loop.
Unrelated but probably replace scanf with fgets or use scanf with length specifier For example
scanf("%99s",string1)
Things I can see wrong at first glance:
Your loop goes over MAX_STRING, it only needs to go over the length of s.
Your iteration should cover only the length of the string, but indexes start at 0 and not 1. for (i=0; i<=len; i++) is not correct.
You should also compare the contents of the pointer and not the pointers themselves. if(*word == *s)
The pointer advance logic is incorrect. Maybe treating the pointer as an array could simplify your logic.
Another unrelated point: A different algorithm is to hash the characters of string1 to a map, then check each character of the string2 and see if it is present in the map. If all characters are present then return 1 and when you encounter the first one that is not present then return 0. If you are only limited to using ASCII characters a hashing function is very easy. The longer your ASCII strings are the better the performance of the second approach.
Here is a one-liner solution, in keeping with Henry Spencer's Commandment 7 for C Programmers.
#include <string.h>
/*
* Does l contain every character that appears in r?
*
* Note degenerate cases: true if r is an empty string, even if l is empty.
*/
int contains(const char *l, const char *r)
{
return strspn(r, l) == strlen(r);
}
However, the problem statement is not about characters, but about letters. To solve the problem as literally given in the question, we must remove non-letters from the right string. For instance if r is the word error-prone, and l does not contain a hyphen, then the function returns 0, even if l contains every letter in r.
If we are allowed to modify the string r in place, then what we can do is replace every non-letter in the string with one of the letters that it does contain. (If it contains no letters, then we can just turn it into an empty string.)
void nuke_non_letters(char *r)
{
static const char *alpha =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
while (*r) {
size_t letter_span = strspn(r, alpha);
size_t non_letter_span = strcspn(r + letter_span, alpha);
char replace = (letter_span != 0) ? *r : 0;
memset(r + letter_span, replace, non_letter_span);
r += letter_span + non_letter_span;
}
}
This also brings up another flaw: letters can be upper and lower case. If the right string is A, and the left one contains only a lower-case a, then we have failure.
One way to fix it is to filter the characters of both strings through tolower or toupper.
A third problem is that a letter is more than just the 26 letters of the English alphabet. A modern program should work with wide characters and recognize all Unicode letters as such so that it works in any language.
By the time we deal with all that, we may well surpass the length of some of the other answers.
Extending the idea in Rajiv's answer, you might build the character map incrementally, as in containsLetters2() below.
The containsLetters1() function is a simple brute force implementation using the standard string functions. If there are N characters in the string (haystack) and M in the word (needle), it has a worst-case performance of O(N*M) when the characters of the word being looked for only appear at the very end of the searched string. The strchr(needle, needle[i]) >= &needle[i] test is an optimization if there are likely to be repeated characters in the needle; if there won't be any repeats, it is a pessimization (but it can be removed and the code still works fine).
The containsLetters2() function searches through the string (haystack) at most once and searches through the word (needle) at most once, for a worst case performance of O(N+M).
#include <assert.h>
#include <stdio.h>
#include <string.h>
static int containsLetters1(char const *haystack, char const *needle)
{
for (int i = 0; needle[i] != '\0'; i++)
{
if (strchr(needle, needle[i]) >= &needle[i] &&
strchr(haystack, needle[i]) == 0)
return 0;
}
return 1;
}
static int containsLetters2(char const *haystack, char const *needle)
{
char map[256] = { 0 };
size_t j = 0;
for (int i = 0; needle[i] != '\0'; i++)
{
unsigned char c_needle = needle[i];
if (map[c_needle] == 0)
{
/* We don't know whether needle[i] is in the haystack yet */
unsigned char c_stack;
do
{
c_stack = haystack[j++];
if (c_stack == 0)
return 0;
map[c_stack] = 1;
} while (c_stack != c_needle);
}
}
return 1;
}
int main(void)
{
assert(containsLetters1("this_is_a_long_string","gagahats") == 1);
assert(containsLetters1("this_is_a_longstring","gaz") == 0);
assert(containsLetters1("hello","p") == 0);
assert(containsLetters2("this_is_a_long_string","gagahats") == 1);
assert(containsLetters2("this_is_a_longstring","gaz") == 0);
assert(containsLetters2("hello","p") == 0);
}
Since you can see the entire scope of the testing, this is not anything like thoroughly tested, but I believe it should work fine, regardless of how many repeats there are in the needle.

Find character frequency in a string

Im trying to find character frequency in a string,i wrote the following code,but it does'nt show any output.All im trying is to fill the character array with respective counts.
When i tried to debug,it some how gives output,but prints some garbage value.
#include<stdio.h>
/* Program for printing character frequency in string */
charcount(char *,int *);
int main()
{
int n,i=0;
printf("Enter n :");
scanf("%d",&n);
char var[n];
int count[100]; // array for storing character frequency
printf("Enter string :");
fflush(stdin);
scanf("%s",var);
charcount(var,count); // calling frequeny function
for(i=0;i<strlen(count);i++)
{
printf("%d\n",count[i]);
}
getch();
return 0;
}
charcount(char *p,int *q)
{
for(;*p;p++)
{
q[*p]++;
}
}
You have few problems in your code:
count array is not initialized.
You are applying strlen() on an integer array.
count array should be 256 (count[256]) to cover all possible ascii chars. For example, if your input is abcd you'll go out of bound of array as d is 100.
You are printing the wrong count:
printf("%d\n",count[i]); should be printf("%d\n",count[var[i]]);
Declare proper prototype for charcount().
After fixing these:
#include<stdio.h>
/* Program for printing character frequency in string */
void charcount(char *,int *);
int main()
{
int n,i=0;
printf("Enter n :");
scanf("%d",&n);
char var[n];
int count[256]={0}; // array for storing character frequency
printf("Enter string :");
scanf("%s",var);
charcount(var,count); // calling frequeny function
for(i=0;i<strlen(var);i++)
{
printf("%d\n",count[var[i]]);
}
return 0;
}
void charcount(char *p,int *q)
{
for(;*p;p++)
{
q[*p]++;
}
}
Make sure to compile in C99 or C11 (e.g. gcc -std=c99 file.c) mode as VLAs are not supported in earlier standards of C.
You need to initialize your count array. Otherwise it will have garbage values in it by default. You can initialize the whole array to 0 like so:
int count[100] = {0};
Your count array may not be large enough to hold all printable values (even assuming ASCII), and it should be 0 initialized. Your for loop should be checking against the length of var, not count, since you cannot sensibly treat the count integer array as a string.
int count[1<<CHAR_BIT] = {};
/*...*/
for(i=0;i<strlen(var);i++)
{
printf("%d\n",count[var[i]]);
}
Well, it really depends on what you want to output. If you intend to output all of count, then:
for(i=0;i<sizeof(count)/sizeof(count[0]);i++)
{
printf("%d\n",count[i]);
}
int count is nothing but a hashmap
Your code will not work for this string "abcd"
count['a'] = val // Works fine ASCII value of a is 97
count['b'] = val // Works fine ASCII value of a is 98
count['c'] = val // Works fine ASCII value of a is 99
count['d'] = val ; // Undefined Behaviour ASCII value of d is 100
The size should be equal to ASCII set length
int count[128] = {};
JAVA program to print "*" as much times as the occurrence of a character in String.
Or char_in_String : frequency of char_in_String
Instead of * you can print frequency count
public class CharFreq
{
public static void main(String[] args)
{
String s = "be yourself "; System.out.println(s);
int r=0;
char[] str = s.toCharArray();
for (int i = 0; i < str.length; i++)
{
int cnt = 0;
if (str[i] != ' ')
{
for (int j = 0; j < str.length; j++)
{
if (str[i] == str[j])
{
cnt++; r=j;
}
}
if(i==r)
{
System.out.print(str[i] + ":");
for (int k = 1; k <=cnt; k++)
System.out.print("*");
System.out.println();
}
}
}
}
}
Output:
be yourself
b:*
y:*
o:*
u:*
r:*
s:*
e:**
l:*
f:*
Your count[100] is not large enough. Assume you only enter "A - Z" or "a - z" it's still not large enough because 'z' is 122, then your charcount will increase count[122].
You should consider change int count[100] to int count[128] = { 0 }

Fill dynamically sized array in C++ and use the values

I'd like to fill a char-array dynamically and check whether the contained values are valid integers, here's what I got so far:
for(int i = 0; i < 50000; i++)
{
if(input[i] == ',')
{
commaIndex = i;
}
}
commaIndex is the index of a comma inside a file, numerical values should have been entered before a comma, file looks like this: -44,5,19,-3,13,(etc), it's important for this part:
char *tempNumber = new char[commaIndex];
Fill tempNumber (which should presumably be just as big as the number due to my dynamic allocation) so I don't have a number in a size 50000 char-array (named input).
for(int i = 0; i < commaIndex; i++)
{
cout << i << "\n";
tempNumber[i] = input[i];
}
And now I want to use it:
if(!isValidInteger(tempNumber))
{
cout << "ERROR!\n";
}
Unfortunately, tempNumber always seems to be of size 4 irregardless of the value of "commaIndex", i.e. I get the following output:
(Inputdata: 50000,3,-4)
commaIndex: 5
content of tempNumber: 5000 (one 0 missing)
commaIndex: 1
content of tempNumber: 3²²² (notice the 3 ^2s)
commaIndex: 2
content of tempNumber: -4²²
Any ideas?
One more thing: This is for a homework assignment and I am not allowed to use any object-oriented element of C++ (this includes strings and vectors, I've been there and I know it would be SO easy.)
Thanks,
Dennis
You might be interested by the strtol function.
You may also consider using strtok() with sscanf(). Notice, that strtol() does not allow you to check for errors since it simply returns (perfectly valid) value 0 on parse error. On the other hand, sscanf() returns number of successfully read items, so you may easily check if there was an error while reading a number.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int i = 0;
char str[] = "1,2,-3,+4,a6,6";
/* calculate result table size and alloc */
int max = 1;
char* tmp = str;
while (*tmp)
if (*tmp++ == ',')
++max;
int* nums = malloc(sizeof(int) * max);
/* tokenize string by , and extract numbers */
char* pch = strtok(str, ",");
while (pch != NULL) {
if (sscanf(pch, "%d", &nums[i++]) == 0)
printf("Not a number: %s\n", pch);
pch = strtok(NULL, ",");
}
/* print read numbers */
for (i = 0; i < max; ++i)
printf("%d\n", nums[i]);
free(nums);
return 0;
}

Resources