C- sort array alphabetically from stdin [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have to make a program in C which reads input from standard input and writes on the screen, strings order alphabetically. Can you please help me?
Here is the program:
#include <stdio.h>
#include <string.h>
int main (int argc, char *argv[])
{
char tabela[100][50];
int i=0;
int j,k;
char string[50];
char temp[50];
while(fgets(string,sizeof(string), stdin) != NULL)
{j=0;
while(j<strlen(string)){
tabela[i][j]=string[j++];
}
i++;
}
for(j=0; j < i ; j++){
for(k=j+1; k< i; k++)
{
if(strcmp(tabela[j],tabela[k]) > 0)
{
strcpy(temp,tabela[j]);
strcpy(tabela[j],tabela[j]);
strcpy(tabela[k],temp);
}
}
}
for (j = 0; j <i; j++){
printf("%s\n", tabela[j]);
}
// sort(tabela,i);
/* for(k = 0; k <=i;k++){
printf("\n");
for(j = 0; j <=i;j++) {
printf("%c", tabela[j][k]);
} //for */
/*
}//for */
return 0;
}//main
Thanks

One opportunity is, to run through a selection sort:
/* selection sort */
void sort(char **a, int n) {
int min, i, j;
char t[50];
for (i = 0; i < n; i++)
{
min = i;
for (j = i+1; j < n; j++)
{
if (strcmp(a[j],a[min]) < 0) min = j;
}
strcpy(t,a[min]);
strcpy(a[min],a[i]);
strcpy(a[i],t);
}
}

C/C++ provides a library for sorting in stdlib.h called "qsort" (quicksort) here
If you need an example:
Basically, you will need to include the required library "stdlib.h" and "string.h" first, then you will need to define a comparison function.
int cmp(const void* a, const void* b)
{
int arg0 = *(char*) a, arg1 = *(char*)b;
return arg0-arg1;
}
Supposed that you have a char array of length 100.
char example[100] = "adfasdfasdfsdasdfasdfafhtyjytjukvr";
Then you call the function qsort like this:
qsort(example,strlen(example),sizeof(char),cmp);
There you go :)
Alternatively, in C++, there are another built-in sorting functions std::sort() and std::stable_sort() available in the header <algorithm> which can not only work with your char array, but also other C++ containers. You may call it like this:
std::sort(example,example+strlen(example));
Further reading:
C++ containers
C++ sort
C++ stable sort

I presume this is an exercise in writing sorting code, so (to avoid doing your homework for you) I'll stick with general suggestions, based on sorting exercises and real-world sorts I've written.
Sorting a list during input from console begs for an insertion sort -- that is, sorting is done as the list is input, so that a "very short time" after pressing ENTER for each entry, the list is fully sorted (ideally, short enough the user can't tell anything was done before the next entry prompt is presented). Sorting with large list elements can be very time consuming, hence the common use of tag sorts (where you sort tags instead of the actual list elements), but it's unlikely you'll have that level of element size from manual entry. A very long list can give similar problems (depending on the efficiency of the search algorithm), but again, that's a problem limited by the entry method.
With your list limited (by array declaration) to 100 elements no more than 50 characters long, the user would never notice the delay if you used a simple step-through test and wholesale move-down for elements that need to be after the new element (on a modern computer, the sort steps after insertion wouldn't exceed a few milliseconds execution time even in an interpreting language), but (on the assumption you're learning something that will be of use later for larger programs and data sets) it's far more efficient to use a binary tree search and linked list; you could get that kind of insertion time for a list of thousands of elements each thousands of bytes long if you only have to look at a tiny fraction of them and never have to move any of them, but only shuffle integers in a tag array.

Related

Need help to identify the longest string separated by space [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I need to make a code that identifies the longest string of characters that a separated by space. If there are characters of same length, write them both.
Ex:
Input = Java flow car tree
Output = Java flow tree
Her is the code i wrote
#include <stdio.h>
#include <stdlib.h>
int main()
{
char cuv[100], big[100];
int i;
printf("Scrieti cuvintele\n");
gets(cuv);
cuv[0] = big[0];
for(i = 0; cuv[i] = '/0'; i++){
if(cuv[i] > big[i]){
big[i] = cuv[i];
}
}
printf("%s", big);
return 0;
}
The problem is i dont know very well how char works. So i have little clue on what to do. I ask of you on how to use the char set to be able to count strings in a specific way.
Here is a very simple solution. Try to understand the code. Note the code uses some of the functions from #include<string.h>. So, before going through the code please go through string.h header file and understand the standard functions it provides.
Anyways, here is a very basic program,(feel free to modify it to your needs)
#include<stdio.h>
#include<string.h>
#define MAX 256
int main(){
char input[MAX],*tmp=NULL;
char *word_list[MAX],*word=NULL;
int flag[MAX];
int i=0,index=0,m=0,largest_len=0;
//Get Input From User
printf("Enter Input:\n");
fgets(input,MAX,stdin);
//If using fgets then use strchr() to locate '\n' and replace it with '\0'(null terminating char)
if((tmp=strchr(input,'\n')) != NULL){
*tmp='\0';
}
//Use strtok() function to split the sentence/input into words separated by space
//and store them in an array of char pointers(or more like array of strings)
word = strtok(input," ");
word_list[index] = word;
index++;
while(word != NULL && i<MAX){
word=strtok(NULL," ");
if(word != NULL){
word_list[index] = word;
index++;
}
}
//find the word with the largest lenght
for(i=0;i<index;i++){
if(strlen(word_list[i]) >= largest_len){
largest_len = strlen(word_list[i]);
}
}
//Then store the index of words which have their lenght equal to the largest lenght
for(i=0;i<index;i++){
if(strlen(word_list[i]) == largest_len){
flag[m] = i;
m++;
}
}
//Print the largest words
m=0;
printf("Largest Word('s):");
for(i=0;i<index;i++){
if(flag[m] == i){
printf("%s ",word_list[i]);
m++;
}
}
return 0;
}
The code you've posted doesn't seem to even come close to what you're trying to do -- so much so that it's really not salvageable towards a solution.
That said, think about your "large" (complete) problem as a series of smaller problems instead; each smaller problem is easier to solve than the single larger problem. Your problems seem to be:
1) Input your raw data.
2) Split your raw data into words. You could manually walk through your data looking for spaces and doing what you feel appropriate when you find them, or you could figure out how to use strtok() to parse data for you. Given where you are with your language understanding, doing it manually is probably a better learning experience.
3) Determine the length of the largest word in your collection.
4) Go through your entire collection and output each word whose length is equal to that largest length.
For problem 1, you seem to have this accomplished (but pay attention to the suggestions people have given you about better ways to do it).
Problem 2 might be the most challenging. There are several ways one can go about it. I'm not going to provide a solution, but this snippet is a small start:
for (i = 0; cuv[i] != '\0'; ++i) {
/* do something */
}
Pay attention to the middle term of the for loop; it's not making an assignment to cuv[i] (I point this out because in your posted program, you are making an assignment, which is really not what you intend.) It is comparing the character to the standard C string termination.
You'll need to look at each character as you go through the loop and decide if you are increasing the current word, ending the previous word, starting a new word, or just skipping repetitive whitespace.
You'll need to store a pointer to each word somewhere so that the full set of words will be available to steps 3 and 4.
Note that you could perform step 3 while you're doing this but you should not for now. It would make your program more efficient, but it merges the steps together and while learning, you don't need that.
Problem 3 requires you to be aware that strlen(const char *s) will return the length of s, where s is a properly terminated C string.
To solve this you will simply iterate through your full set of words and inspect the length of each; if the length is greater than the previous maximum you will increase your stored maximum. Something like:
unsigned int maxLength = 0;
for (i = 0; i < numberOfWords; ++i) {
if (strlen(word[i]) > maxLength)
maxLength = strlen(word[i]);
}
Finally, for step 4 you will iterate through your list of words again, deciding which ones to print out. Something like:
for (i = 0; i < numberOfWords; ++i) {
if (strlen(word[i]) == maxLength)
printf("%s\n", word[i]);
}

How to improve execution speed on large data sort in C

I managed to roll off an insertion sort routine as shown:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
int n;
char l;
char z;
} dat;
void sortx(dat* y){
char tmp[sizeof(dat)+1];
dat *sp=y;
while(y->l){
dat *ip=y;
while(ip>sp && ip->n < (ip-1)->n){
memcpy(tmp,ip,sizeof(dat));
memcpy(ip,ip-1,sizeof(dat));
memcpy(ip-1,tmp,sizeof(dat));
ip--;
}
y++;
}
}
void printa(dat* y){
while(y->l){printf("%c %d,",y->l,y->n);y++;}
printf("\n");
}
int main(int argc,char* argv[]){
const long sz=10000;
dat* new=calloc(sz+2,sizeof(dat));
dat* randx=new;
//fill struct array with random values
int i;
for (i = 0 ; i < sz ; i++) {
randx->l = (unsigned char)(65+(rand() % 25));
randx->n = (rand() % 1000);randx++;
}
//sort - takes forever
sortx(new);
printa(new);
free(new);
return 0;
}
My sorting routine was partly derived from: http://www.programmingsimplified.com/c/source-code/c-program-insertion-sort
but because I am dealing with sorting the array based on the numeric value in the struct, memcpy works for me so far.
The computer I'm using to execute this code has a Pentium 1.6Ghz Processor and when I change sz in the main function to at least 20000, I notice I have to wait two seconds to see the results on the screen.
The reason why I'm testing large numbers is because I want to process server logs in C and will be sorting information by timestamps and sometimes the logs can become very large, and I don't want to put too much strain on the CPU as it is running other processes already such as apache.
Is there anyway I can improve this code so I don't have to wait two seconds to see 20000 structs sorted?
There is already a function that does this, and it's built in in the C standard library: qsort. You just have to provide suitable comparison function.
This function has to return -1 if the item taken as a left argument should be put earlier in the desired order, 1 if it should be put later, or 0 if the items are to be considered equal by qsort.
int dat_sorter(const void* l, const void* r)
{
const dat* left = (const dat*)l;
const dat* right = (const dat*)r;
if(left->n > right->n)
return 1;
else if(left->n < right->n)
return -1;
else
return 0;
}
void sortx(dat* y)
{
/* find the length */
dat* it = y;
size_t count = 0;
while(it->l)
{
count++;
it++;
}
/* do the sorting */
qsort(y, count, sizeof(dat), dat_sorter);
}
If you want to speed it up even more, you can make sortx function take length of the array, so the function won't need to figure it out on its own.
Use quick sort, heap sort, or bottom up merge sort. Wiki has examples of these in their articles, and typically have more complete examples on each article's talk page.
Insertion sort has O(n^2) time complexity, and there are other algorithms out there that will give you O(nlogn) time complexity like mergesort, quicksort, and heapsort. It looks like you are sorting by an integer, so you also might want to consider using LSD radix sort, which is O(n) time complexity.

finding how many times an element has repeated in c

I've got a c study which it must print all the numbers in an array then how many times they repeated.
int lottery(int a,int b,int c,int d,int e,int f,int i,int count)
{
printf("Enter the loop count:");
scanf("%d",&d);
a=time(NULL);
srand(a);
int genel[100][100];
int hepsi[50]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49};
count=0;
for(e=0;e<=d-1;e++)
{
for(b=0;b<=5;b++)
{
genel[e][b]=(rand()%49+1);
while(i>=0 && i<=49)
{
if(genel[e][b]==hepsi[i])
{
count=count+1;
}
else{
count=count;
}
}
printf("%d->%d\t",genel[e][b],count);
}
}
}
This doesnt work obviously. the output must be something like that
1-->0 2-->3 3-->15 etc
TY for your help, cheers :)
It is important that you understand what you are doing, naming is therefore very important. Nesting loops is okay if you know what you are doing. An easier to understand approach would be:
void lottery() {
int i, j //forloop counters
int randArray[100][100]; //array for random values
srand(Time(NULL)); //set random seed based on system time
//set random values
for(i = 0; i < 100; i++) {
for(j = 0; j < 100; j++) {
randArray[i][j] = rand()%49 + 1; //sets random ranging from 1 to 49 (49 incl)
}
}
//here you can start the counting procedure, which I won't spoil but ill give some hints below
}
There are a few options, first the easy lazy approach:
use a loop over all the values, 'int number' from 1 up to 49, inside that forloop use two forloops to search through the whole array, incrementing int x everytime you encounter the value 'number'. After youve searched through the whole array, you can use printf("%d -> %d", number, x); to print the value, set x to zero and count another number.
Another approach is as u tried,
create an array with for each number a location where you can increment a counter. Loop through the whole array now using two for-loops, increment the arraylocation corresponding to the value which youve found at randArray[i][j]. Afterwards print the array with counts using another forloop.
I suggest you try to clean up your code and approach, try again and come back with problems you encounter. Good luck!
sorry if this wasn't helpful to you, I tried to spoil not too much because according to my own experience programming should be learned by making mistakes.

Alphabetically Ordering an array of words

I'm studying C on my own in preparation for my upcoming semester of school and was wondering what I was doing wrong with my code so far.
If Things look weird it is because this is part of a much bigger grab bag of sorting functions I'm creating to get a sense of how to sort numbers,letters,arrays,and the like! I'm basically having some troubles with the manipulation of strings in C currently.
Also, I'm quite limited in my knowledge of C at the moment!
My main Consists of this:
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
int numbers[10];
int size;
int main(void){
setvbuf(stdout,NULL,_IONBF,0); //This is magical code that allows me to input.
int wordNumber;
int lengthOfWord = 50;
printf("How many words do you want to enter: ");
scanf("%i", &wordNumber);
printf("%i\n",wordNumber);
char words[wordNumber][lengthOfWord];
printf("Enter %i words:",wordNumber);
int i;
for(i=0;i<wordNumber+1;i++){ //+1 is because my words[0] is blank.
fgets(&words[i], 50, stdin);
}
for(i=1;i<wordNumber+1;i++){ // Same as the above comment!
printf("%s", words[i]); //prints my words out!
}
alphabetize(words,wordNumber); //I want to sort these arrays with this function.
}
My sorting "method" I am trying to construct is below! This function is seriously flawed, but I'd thought I'd keep it all to show you where my mind was headed when writing this.
void alphabetize(char a[][],int size){ // This wont fly.
size = size+1;
int wordNumber;
int lengthOfWord;
char sortedWords[wordNumber][lengthOfWord]; //In effort for the for loop
int i;
int j;
for(i=1;i<size;i++){ //My effort to copy over this array for manipulation
for(j=1;j<size;j++){
sortedWords[i][j] = a[i][j];
}
}
//This should be kinda what I want when ordering words alphabetically, right?
for(i=1;i<size;i++){
for(j=2;j<size;j++){
if(strcmp(sortedWords[i],sortedWords[j]) > 0){
char* temp = sortedWords[i];
sortedWords[i] = sortedWords[j];
sortedWords[j] = temp;
}
}
}
for(i=1;i<size;i++){
printf("%s, ",sortedWords[i]);
}
}
I guess I also have another question as well...
When I use fgets() it's doing this thing where I get a null word for the first spot of the array. I have had other issues recently trying to scanf() char[] in certain ways specifically spacing my input word variables which "magically" gets rid of the first null space before the character. An example of this is using scanf() to write "Hello" and getting " Hello" or " ""Hello"...
Appreciate any thoughts on this, I've got all summer to study up so this doesn't need to be answered with haste! Also, thank you stack overflow as a whole for being so helpful in the past. This may be my first post, but I have been a frequent visitor for the past couple of years and it's been one of the best places for helpful advice/tips.
You're going to like this - it's a derivation of QSort, adapted to your situation. It may not work quite perfectly for you without a touchup here or there (TEST FIRST!):
void qsort (Strings[], NumberOfItems)
{
char Temp[51]; // Assumes your max string length of 50
int I1 = 0; // Primary index
int I2 = 0; // Index + 1
int NumberOfItems_1 = 0;
bool Swapped = false;
do // Outer loop
{
Swapped = false;
// Decrement our limit
NumberOfItems--;
// Save time not performing this subtraction many times
NumberOfItems_1 = NumberOfItems - 1;
// Repeatedly scan the list
for (I1 = 0; I1 < NumberOfItems_1; I1++)
{
// Save time not performing this addition many times
// I1 points to the current string
// This points to the next string
I2 = I1 + 1;
// If the current string is greater than the next string in the list,
// swap the two strings
if (strcmp(Strings[I1], Strings[I2]) > 0)
{
strcpy (Temp, Strings[I1]);
strcpy (Strings[I1], Strings[I2]);
strcpy (Strings[I2], Temp);
Swapped = true;
}
}
}
while (Swapped); // Break out when we've got nothing left to swap
}
I see a few things wrong with your code off the bat. First, you declare sortedWords as a multidimensional array (since you have sortedWords[wordnumber][lengthofword], but you try to use it with only one index later on.. this doesn't work! Also, your passing of the 2D array is not valid. Check out this post to see the valid ways to pass a 2D array: Passing a 2D array to a C++ function
Function declaration and definition
The function declaration is invalid, as you've found out. You must specify the size of every dimension of the array except the first, so you might write:
void alphabetize(char a[][SOMESIZE], int size)
However, you have a non-constant second dimension (so you're using a VLA or variable length array), which means that you need to pass both sizes to the function, and pass them before you pass the array:
void alphabetize(int size, int length, char a[size][length])
and then invoke it:
alphabetize(wordNumber, lengthOfWords, words);
Of course, you should also declare the function before you try calling it.
There are probably other issues to be addressed, but this is the immediate one that jumps out. For example, you need to use size and length to control the loops in the function. You probably don't need to copy the data into the local array (in which case you don't need the local array). Etc.
You should consider compiling with options such as:
gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
-Wold-style-definition -Wold-style-declaration -Werror …
Note that note all versions of GCC support all those options, but use as many as are supported.
Input issue
You have:
int i;
for (i = 0; i < wordNumber + 1; i++) { //+1 is because my words[0] is blank.
fgets(&words[i], 50, stdin);
}
You're stepping out of bounds of your array, which potentially wreaks havoc on your code. The first entry is blank because scanf() leaves the newline in the input buffer. You should read to the end of line before going to line-based input:
int c;
while ((c = getchar()) != EOF && c != '\n')
;
You should also check the fgets() returns a non-null pointer; don't continue if it does.

How can this combination algorithm be modified to run in parallel on a cuda enabled gpu?

I currently have a c program that generates all possible combinations of a character string. Please note combinations, not permutations. This is the program:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//Constants
static const char set[] = "abcd";
static const int setSize = sizeof(set) - 1;
void brute(char* temp, int index, int max){
//Declarations
int i;
for(i = 0; i < setSize; i++){
temp[index] = set[i];
if(index == max - 1){
printf("%s\n", temp);
}
else{
brute(temp, index + 1, max);
}
}
}
void length(int max_len){
//Declarations
char* temp = (char *) malloc(max_len + 1);
int i;
//Execute
for(i = 1; i <= max_len; i++){
memset(temp, 0, max_len + 1);
brute(temp, 0, i);
}
free(temp);
}
int main(void){
//Execute
length(2);
getchar();
return 0;
}
The maximum length of the combinations can be modified; it is currently set to 2 for demonstration purposes. Given how it's currently configured, the program outputs
a, b, c, d, aa, ab, ac, ad, ba, bb, bc, bd, ca, cb, cc...
I've managed to translate this program into cuda:
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//On-Device Memory
__constant__ char set_d[] = "adcd";
__constant__ int setSize_d = 4;
__device__ void brute(char* temp, int index, int max){
//Declarations
int i;
for(i = 0; i < setSize_d; i++){
temp[index] = set_d[i];
if(index == max - 1){
printf("%s\n", temp);
}
else{
brute(temp, index + 1, max);
}
}
}
__global__ void length_d(int max_len){
//Declarations
char* temp = (char *) malloc(max_len + 1);
int i;
//Execute
for(i = 1; i <= max_len; i++){
memset(temp, 0, max_len+1);
brute(temp, 0, i);
}
free(temp);
}
int main()
{
//Execute
cudaSetDevice(0);
//Launch Kernel
length_d<<<1, 1>>>(2);
cudaDeviceSynchronize();
getchar(); //Keep this console open...
return 0;
}
The cuda version of the original program is basically an exact copy of the c program (note that it is being compiled with -arch=sm_20. Therefore, printf and other host functions work in the cuda environment).
My goal is to compute combinations of a-z, A-Z, 0-9, and other characters of maximum lengths up to 10. That being the case, I want this program to run on my gpu. As it is now, it does not take advantage of parallel processing - which obviously defeats the whole purpose of writing the program in cuda. However, I'm not sure how to remove the recursive nature of the program in addition to delegating the threads to a specific index or starting point.
Any constructive input is appreciated.
Also, I get an occasional warning message on successive compiles (meaning it sporadically appears): warning : Stack size for entry function '_Z8length_di' cannot be statically determined.
I haven't pinpointed the problem yet, but I figured I would post it in case anyone identified the cause before I can. It is being compiled in visual studio 2012.
Note: I found this to be fairly interesting. As the cuda program is now, its output to the console is periodic - meaning that it prints a few dozen combinations, pauses, prints a few dozen combinations, pauses, and so forth. I also observe this behavior in its reported gpu usage - it periodically swings from 5% to 100%.
I don't think you need to use recursion for this. (I wouldn't).
Using printf from the kernel is problematic for large amounts of output; it's not really designed for that purpose. And printf from the kernel eliminates any speed benefit the GPU might have. And I assume if you're testing a large vector space like this, your goal is not to print out every combination. Even if that were your goal, printf from the kernel is not the way to go.
Another issue you will run into is storage for the entire vector space you have in mind. If you have some processing you intend to do on each vector and then you can discard it, then storage is not an issue. But storage for a vector space of length n=10 with "digits" (elements) that have k=62 or more possible values (a..z, A..Z, 0..9, etc.) will be huge. It's given by k^n, so in this example that would be 62^10 different vectors. If each digit required a byte to store it, that would be over 7 trillion gigabytes. So this pretty much dictates that storage of the entire vector space is out of the question. Whatever work you're going to do, you're going to have to do it on the fly.
Given the above discussion, this answer should have pretty much everything that you need. The vector digits are handled as unsigned int, you can create whatever mapping you want between unsigned int and your "digits" (i.e. a..z, A..Z, 0..9, etc.) In that example, the function that was performed on each vector was testing if the sum of the digits matched a certain value, so you could replace this line in the kernel:
if (vec_sum(vec, n) == sum) atomicAdd(count, 1UL);
with whatever function and processing you wanted to apply to each vector generated. You could even put a printf here, but for larger spaces the output will be fragmented and incomplete.

Resources