Using C, I have an array of strings, some are duplicates. I'm trying to count the number of unique strings. Code:
for(i=0; i<size; i++){
flag=0;
if(strcmp(" ", tArr[i])!=0){
for(j=i; j<size; j++){
if(strcmp(tArr[i], tArr[j])==0){
if (flag<1){
flag=1;
k++;
}
strcpy(tArr[j], " ");
}
}
}
}
First for loop goes through the whole array
Set flag to zero for each iteration
Using blanks as another flag, if an index is blank, that means that word has already been counted, move to next index
Compare that index to every index after it, thus j=i
If the secondary index matches the first
If that word has not been found yet
Trigger the flag
Add to k, the unique word count
Set every remaining instance of that word to a blank space, to match line 3
Instead of setting k to the unique word count, it gets set to the total word count. Using printed flags I was able to tell that the function makes it all the way through, even to after line
I still can't tell how it makes it to line 8 every iteration of the outermost for loop.
Adapting your code, try something like this:
for (i = 0; i < size; i++) {
for (j = i + 1; j < size; j++)
if (strcmp(tArr[i], tArr[j]) == 0)
break;
if (j == size)
unique_count++;
}
There should be no need to destroy the duplicates if you are just counting, however if you still wish to do that I would suggest a null string instead of one containing a space.
Related
I've been attempting to take a character array with some indices having characters and some having null characters and change it to only an array with characters - shifting over indices to remove the null spaces when need be.
This is my approach so far:
char *args[256];
void removeNulls(){
for(int i=0; i<=token; i++){
if(args[i] == '\0'){
shiftleft(i);
}
}
}
void shiftleft(int start){
for(int i=start; i<token; i++){
*(args+i) = *(args + i +1);
}
}
However, when I do this and print out the result I notice that in the args array,
that is the initial args array, it consists of : null, null, 1,2,3,4 after removing nulls this array becomes null,1,2,3,4 instead of the desired 1,2,3,4. Is there something I'm missing in my loop conditions to account for this?
One index gets skipped every time you hit a null, because you always increment i even when you are skipping. You should increment i only when not skipping, for example like this:
for (int i=0; i<=token; ) {
if (args[i] == '\0') {
shiftleft(i);
} else {
i++;
}
}
By the way, the algorithm is not optimal when there are multiple nulls, because for every null, you shift the entire remaining part. It is possible to shift the contents over the nulls in a single pass, by tracking the current index and the next index to fill. For each null value, the next fill index will get one step behind the current index.
for (int i=0, next = 0; i<=token; i++) {
if (args[i] != '\0') {
args[next++] = args[i];
}
}
Last thing, what about the excess elements? That is, for the input null, null, 1, 2, 3, token, the resulting content will be 1, 2, 3, 2, 3, token. Is that OK like that? I suggest to check your requirement, as maybe you have some tasks concerning these remaining elements. I leave that for your exercise.
When i=0, when shiftleft(0) is called,
Whatever value is at address pointed by (args+i)->(args+0)->"null" is replaced with (args+i+1)->(args+0+1)->"null".
This is why your output prints null,1,2,3,4.
Change your input to null,1,2,3,4 and you will see the difference.The output will then be 1,2,3,4
I am attempting to solve this problem but I'm not sure why my solution doesn't work. My attempts at debugging tell me that the solution is attempting to access indices outside of the bounds of some of the data structures, but this does not make sense to me as it seems like my for-loop test would would.
There are probably many other issues with this solution besides this.
I'm also 90% sure that there's a more efficient way to do this. Could you help me figure out what it is I've done wrong here?
If there is a more efficient solution, what would it be? I'm struggling to deal with keeping track of the same number of spaces in the same order in an efficient way.
If any more information is necessary, please let me know and I will update.
public static void printReversed(String line){
Scanner console = new Scanner(line);
ArrayList<String> list = new ArrayList<String>(); // keeps track of words in line
int spaceOccur = 0; // keeps track of the number of times there are spaces
while (console.hasNext()){
list.add(console.next());
spaceOccur++;
}
int[] spaces = new int[spaceOccur]; // keeps track of number of spaces for each occurrence of spaces
int count = 0; // for spaces[] traversal
// searches through original input to get number of spaces
for (int i = 0; i < line.length() - 1; i++){
if (line.charAt(i) == ' '){
int j = i;
int num = 0;
// traversal through spaces to count how many
while (line.charAt(j) == (' ')){ // first error here
num++;
j++;
}
i = j; // updates for loop counter to point past spaces
spaces[count] = num; // saves number of spaces
count++;
}
}
// printing reversed input
for (int k = 0; k < list.size(); k++){
// prints reversed chars
for (int m = list.get(k).length(); m > 0; m++){
System.out.print(list.get(k).charAt(m));
}
// prints spaces
for (int n = 0; n < spaces[k]; n++){
System.out.print(" ");
}
}
}
I'd say that you're on right tracks, but some places need some closer inspection. The first loop seems to have some problems: The j++ is probably the one that goes beyond boundaries of the array - at least if you have spaces at the end of your string. And the whole loop itself seems to ignore the last character of the line.
Are you sure you even need this first loop? If I have understood correctly, the ScannerĀ“s next() will give you strings between the spaces; in the case of two consecutive spaces I think it should return you an empty string. In this case you could just loop the list the way you do in the end of your function, and print a space character when you encounter an empty string in your list. Otherwise just print the word backwards, just like you already do (except that it should be m-- instead of m++ in the last for loop).
But if the Scanner won't give you the empty strings when there are two or more consecutive space characters, I bet the string's split() method should work.
Hey this is my first post here. i have been assigned with an excercise to count the most frequent word in c programming language. first and foremost i need to read a number which tells me how many words i will have to read. then i need to use calloc with max element size 50. after that i read the strings. my original idea was to create a one-dimensional array which im gonna later sort alphabetically and then counting and printing the most frequent word would be easy. but after some hours of research i found out i need to use a two-dimensional array and things went out of control. ive been studying computer science for 3 months now and this exercise seems tough. do u have any other suggestions?. the example was this:
10
hello
world
goodbye
world
thanks
for
all
hello
the
fish
hello
my code so far is
int main()
{
int i, n, j, temp;
int *a;
printf("Eisagete to plhthos twn leksewn:");
scanf("%d",&n);
a = (int*)calloc(n,50);
printf("Eisagete tis %d lekseis:\n",n);
for( i=0 ; i < n ; i++ )
{
scanf("%d",&a[i]);
}
for (i = 0 ; i < ( n - 1 ); i++)
{
for (j = 0 ; j < n - i - 1; j++)
{
if (a[j] > a[j+1])
{
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
dont mind the printfs they are in greek and they are just there to make it look better. i also want to point out that this version is used for integers and not for strings just to start off.
im currently trying a linear search but im not sure if it will help
As you point out, the code you show is related to reading and sorting integers; it is only loosely related to the word counting problem.
How would you count the occurrences of each number? You'd have to
Read the next number;
If you already have a tally for the number, you add one to the tally for that number;
If you've not seen the number before, you create a tally for it and set its count to one.
When all the numbers are read, you search through the set of tallies, looking for the one with the largest count.
Record the number and count of the first entry.
For each subsequent entry:
If the count is larger than the current maximum, record the new maximum count and the entry.
Print the information about the number with the largest count and what that count is.
Replace numbers with words and the general outline will be very similar. You might allocate storage for each string (distinct word) separately.
It is easy to count the number of distinct words or the total number of words as you go. Note that you do not need to store all the words; you only need to store the distinct words. And the count at the front of the list is computer science education gone astray; you don't need the count to make it work (but you probably have to live with it being in the data; the simplest thing is to ignore the first line of input since it really doesn't help very much at all). The next simplest thing is to note that unless they're fibbing to you, the maximum number of distinct words will be the number specified, so you can pre-allocate all the space you need in one fell swoop.
Very simple. Store your words in a 2D array the loop through it and each time you take a word loop through it again starting from the current index and check if there is an equal. ech time the child loop ends check if the number of occurrences is bigger than the last maximum.
#include <stdio.h>
int main()
{
int i, j, occurrence=0, maximum = 0;
char *index_max = NULL;
char wl[10][10] = {"hello","world","goodbye","world","thanks","for","all","hello","the","world"};
for (i=0; i<10; i++){
occurrence = 0;
for (j=i; j<10; j++){
if (!strcmp(*(wl+i), *(wl+j))){
occurrence++;
}
}
if (occurrence>maximum){
maximum = occurrence;
index_max = *(wl+i);
}
}
if (index_max != NULL){
printf("The most frequent word is \"%s\" with %d occurrences.\n", index_max, maximum);
}
return 0;
}
So I'm trying to check if an array that was previously inputted is increasing in intervals of 1, starting with the number 1 and ending with n (n being the array size).
Here's what I got so far:
for (int i =0; i<n;i++){
for (next=i;next<n;next++){
if(arr[i]+1 = arr[next]){
x = 1; //ignore this, it relates to the rest of the code.
}
else{
printf ("\nThis is not a permutation.");
break;
}
}
}
Now, my thinking is that this code would compare parameters that are next to each other, and if the following parameter is equal to the previous +1, then it is obviously increasing by 1. Problem is, when this is false, it wont print "This is not a permutation," and wont break the loop.
Any help would be appreciated.
Also, any insight as to checking if the array starts with the number 1 would be appreciated.
Thanks
Looks like in this line:
if(arr[i]+1 = arr[next]){
You intended comparison:
if(arr[i]+1 == arr[next]){
Have you tried if(arr[i]+1 == arr[next]) instead of if(arr[i]+1 = arr[next])??
If you need to check that a sequence is increasing, why are you comparing every element against the others? You should only need one for loop:
for (i = 1; i < n; i++)
{
if (arr[i - 1] + 1 == arr[i])
... // keep going
else
... // not a permutation
}
Basically, what your code does is check that every element after the i-th one is greater than that i-th one by one. Ultimately, this leads to an impossible case (as two numbers must be equal but must differ by one at the same time).
It sounds like you want to test if arr[0] == 1 and every subsequent array element is 1 greater than the previous element. Isn't that the same as checking your array for the values [1,2,3,...,n]?
for (int i = 0; i < n; ++n) {
if (arr[i] != i + 1) {
printf("\nThis is not a permutation.");
break;
}
}
I am attempting to use strcmp to compare to strings that are stored in an array of structures called index. This index contains a string called webpage and an int called rank. The idea is to compare the two indexes and create a third index that contains the webpages that are the same between the first two indexes and the sum of their respective ranks.
The problem is that when I use the for loop to find the number of similar pages between the indexes it always returns 7. It should only return 4. Am I incorrectly using this function?
int thesame = 0;
for(i = 0; i < 8; i++) {
for(j = 0; j < 7; j++) {
if(strcmp(hotels[i].webpage,seattle[i].webpage) == 0) {
thesame++;
}
}
}
printf("%d\n", thesame);
return 0;
I also understand that I have a lot of hardcoded values for the lengths and this is not good coding practice. I plan to get the program working before I change this.
if (strcmp (hotels[i].webpage, seattle[i].webpage) == 0)
You are using the index i twice. I guess you want rather something like:
if (strcmp (hotels[i].webpage, seattle[j].webpage) == 0)
---------------------------------------^----------------