Porovnavanie vstupu z klavesnice s obsahom txt suboru [C] – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu
Reklama
Reklama

Porovnavanie vstupu z klavesnice s obsahom txt suboru [C] – C / C++ – Fórum – Programujte.comPorovnavanie vstupu z klavesnice s obsahom txt suboru [C] – C / C++ – Fórum – Programujte.com

 

Toto vlákno bylo označeno za vyřešené — příspěvek s řešením.
Hledá se programátor! Plat 1 800 € + bonusy (firma Boxmol.com)
mysh00
Duch
5. 5. 2012   #1
-
0
-

Zdravím, chcel by som poradiť ohľadom jedného čiastkového problému.

Mojou úlohou je vyhľadať, či sa zadaný reťazec nachádza v danom textovom súbore (.txt). Data do daného súboru zapisuje užívateľ prostredníctvom programu, pričom každý riadok program čísluje a každý záznam je v novom riadku. štruktúra zápisu je takáto: číslo riadku. char1; char2; int1; int2;

Slovom: číslo riadku s bodkou doplní program, nasleduje medzera, dva ľubovoľné vložené reťazce a za tým dvakrát integer, všetko oddelené bodkočiarkou s medzerou.

Ja potrebujem zistiť, či nejaké slovo/číslo, ktoré zadám sa v niektorom zázname (=riadku) vyskytuje. Nepotrebujem vedieť na ktorej pozícii, len či tam je alebo nie a nakoniec vypísať všetky záznamy, v ktorých sa hľadaný reťazec vyskytuje.

Moja idea je následovná:

-riadok po riadku nahádzať do nejakého poľa a potom porovnávať reťazce

-ak sa tam hľadaný reťazec vyskytne, tak si poznačiť prvý znak v riadku (=jeho poradie) a potom všetky poznačené riadky vypísať... toto však zatiaľ nerieším, pokúsim sa niečo vymyslieť - ak by sa mi nedarilo, tak sa opýam na konkrétny problém, ale zatiaľ to riešiť nemusíme

Zatiaľ som však veľa času strávil s tou prvou časťou - vyťahovaním riadkov... Skúšal som všetko možné, avšak bez výsledku (nebudem sem dávať kódy, pretože zakaždým som to prepisoval a okrem počítania znakov v každom riadku mi nič nevyšlo a to počítanie znakov mi je zatiaľ k ničomu). Skúšal som v cykle všelijako kopírovať pomocou getc, fgets, fscanf, ale nič mi nefungovalo (skompilovať mi skompilovalo vždy, ale buď to nefungovalo tak ako malo alebo mi to hodilo tuším segmentation fault). Mám taký pocit, že ja to už veľmi prešpekulávam a pritom riešenie bude jednoduché... Vedel by ma niekto nejako ponavigovať? Ďakujem.

Nahlásit jako SPAM
IP: 88.212.40.–
Reklama
Reklama
Jano
~ Anonymní uživatel
53 příspěvků
5. 5. 2012   #2
-
+1
-
Zajímavé

   

FILE* f;

char s[4096];

f=fopen("subor.txt","r"); // otvory subor

fgets(s,sizeof(s),f); // mas v s nacitany riadok 

fclose(f);

ked pridas daky cyklus v ktorom si to rozdelis do tych casti je to asi najrychlejsie.

a potom to cele zabalis do dalsie ho cyklu kde testujes feof(f); aby si presiel cely subor 

Nahlásit jako SPAM
IP: 85.135.131.–
ingiraxo+15
Grafoman
5. 5. 2012   #3
-
0
-

můžeš to udělat tak, že:

1) všechno budeš řešit přímo v procházení souboru, takže pro výpis řádků budeš mít pouze jeden cyklus

2) uložíš všechny řádky do paměti (někam do pole) a s ním potom budeš pracovat

a potom jestli jsem dobře pochopil, tak v každým řádku vyhledáváš ty slova (char1, char2), takže každej řádek budeš muset rozparsovat a vytáhnout z něho tyhle 2 slova, aby si je mohl porovnat s hledaným

pokud bude souhlasit, tak ho někde hned vypíšeš nebo opět uložíš do speciálního pole, který na konci vypíšeš

Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
mysh00
Duch
6. 5. 2012   #4
-
0
-

Vďaka, načítavanie riadkov už je vyriešené, i keď je tam jedna (z môjho pohľadu) anomália, ktorú si nedokážem vysvetliť. Konkrétne s tým načítavaním riadkov, ak som skopíroval kód od "Jano", tak to fungovalo, ak som kód napísal sám analogicky podľa toho aké názvy a premenné som v programe používal, tak to nefungovalo (skompilovalo, ale nerobilo to nič). Konkrétne:

-začiatok kódu, ktorý sa nemení:

#include<stdio.h>
#include<ncurses.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>

int pocetzaznamov(){
int pr,c;
FILE *fr;	
pr=0;
fr=fopen("subor.txt","r");
while ((c = getc(fr)) != EOF){
if (c == '\n') pr++;}
fclose(fr);
return(pr);}


int main(void){
system("clear");
int volba,i,n,fak,stu,k,pz,riadok;
char nazov[40];
char mesto[25];

FILE *fa;
FILE *fr;
printf("\n");
menu:{
system("clear");
printf("|===M======E======N======U===|\n");
printf("|Pridanie zaznamu...........1|\n");
printf("|Zobrazenie zaznamov........2|\n");
printf("|Vyhladanie zaznamu.........3|\n");
printf("|Vymazat subor zaznamov.....4|\n");
printf("|Koniec programu............5|\n");
printf("|===M======E======N======U===|\n");
printf("******************************");
zaciatok:
{printf("\nVolba z hlavneho menu......."); scanf("%d",&volba);
printf("\n");}
}



-kód, ktorý funguje (jedná sa o spodné riadky):

if (volba==3){
 system("clear");
 fr=fopen("subor.txt","r");
 char *hlad;
 char r[4096];
 int c,znaky=0;
 printf("VYHLADANIE ZAZNAMU:\n\n");
 printf("Zadajte vyhladavane kriterium: "); 
 scanf("%s",&hlad);
 pz=pocetzaznamov();
 znaky=0;
 
 for (i=1;i<=pz;i++){
  while ((c=getc(fr))!='\n') znaky++;   
  printf("V %d riadku je %d znakov\n",i,znaky-1);
  znaky=0;
   }
 
 FILE* f;
  
  char s[4096];
  
  f=fopen("subor.txt","r"); 
  
  while(fgets( s, sizeof(s), f) != NULL) puts(s); /*zatial som len laboroval s nacitavanim riadkov, cize som ho len vypisal */
  fclose(f)
   
   
   getchar();
 
}

-kód, ktorý som písal analogicky, ale nerobil nič (posledný while):

if (volba==3){
 system("clear");
 fr=fopen("subor.txt","r");
 char *hlad;
 char r[4096];
 int c,znaky=0;
 printf("VYHLADANIE ZAZNAMU:\n\n");
 printf("Zadajte vyhladavane kriterium: "); 
 scanf("%s",&hlad);
 pz=pocetzaznamov();
 znaky=0;
 
 for (i=1;i<=pz;i++){
  while ((c=getc(fr))!='\n') znaky++;   
  printf("V %d riadku je %d znakov\n",i,znaky-1);
  znaky=0;
   }
 
 while(fgets( r, sizeof(r), fr) != NULL) puts(r);
 fclose(fr); 
   
   
   getchar();
 
}

To len tak pomimo, keďže mám k dispozícií aj funkčnú variantu, len mi nie je jasné, prečo tá druhá nefunguje...

A teraz druhá vec, v tomto cykle:

while(fgets( s, sizeof(s), f) != NULL)

by som chcel testovať, či sa v danom riadku nenachádza hĺadaný výraz zadaný z klávesnice. Skúšal som funkciu strstr, ale v takomto formáte:

while(fgets( s, sizeof(s), f) != NULL) {
	if ((strstr(s,hlad))!=0) puts(s); }
  

to hodí segmenation fault (pri zadávaní hľadanej frázy z klávesnice zadávam niečo, čo sa v danom súbore nachádza).

Skúšal som aj takýto kód, či nie som úplne mimo s tým strstr a vypísalo mi to normálne všetky riadky zo súboru:

while(fgets( s, sizeof(s), f) != NULL) {
	if ((strstr("miso je super","miso")!=0) puts(s); }

Ako by mal správne vyzerať zápis, ak chcem zistiť, či sa reťazec "hlad" (ktorý zadám z klávesnice) v reťazci s (riadok zo súboru) ?

THX!

Nahlásit jako SPAM
IP: 88.212.40.–
jano
~ Anonymní uživatel
53 příspěvků
6. 5. 2012   #5
-
0
-

kod ktory nerobil nic to nerobil lebo si uz bol na konci suboru tak nebolo co citat pozri man k funkcii fseek.

segfault tam mas kvoli tomu ze zapisujes do smernika ktory neukazuje na tebe pridelenu pamat (ak hej tak to je skor nahoda) skus zmenit hlad na pole ;)

Nahlásit jako SPAM
IP: 85.135.188.–
mysh00
Duch
6. 5. 2012   #6
-
0
-

Skúsil som, ale taktiež to nespravilo nič, akurát to bolo bez segfaultu. Kód vyzeral takto (zvyšok nezmenený):

char hlad[100];
char s[4096]; 
scanf("%s",&hlad); 
while(fgets( s, sizeof(s), f) != NULL){
  if ((strstr(s,hlad))!=NULL) puts(s);}
  
   

// edit - napadlo mi, môže to byť tým nulovým znakom na konci hlad?  Teda, či nie je potrebné najprv odstrániť z reťazca nulu na konci a až tak porovnávať.

Nahlásit jako SPAM
IP: 88.212.40.–
ingiraxo+15
Grafoman
6. 5. 2012   #7
-
0
-

Co třeba něco jako:


FILE* file = fopen("soubor.txt", "r");
char buffer[4096];

while (!feof(file))
{
    if (fgets(buffer, sizeof(buffer), file))
    {
        if (!strcmp(buffer, "myText"))
        {
            // pokud je radek stejny jako muj text
        }
    }
}
fclose(file);
Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
mysh00
Duch
6. 5. 2012   #8
-
0
-

Riadok nikdy nebude celý totožny s "myText", pretože vyhľadávané slovo/číslo bude stále iba podmnožinou toho riadku. V riadku sú konkrétne informácie ako názov školy, sídlo (mesto), počet fakúlt a počet študentov, pričom užívateľ nebude zadávať na vyhľadávanie asi všetky parametre súčasne a navyše v štruktúre ako sú tieto dáta zapísane v súbore (bodkočiarka, medzera..).

Nahlásit jako SPAM
IP: 88.212.40.–
ingiraxo+15
Grafoman
6. 5. 2012   #9
-
0
-

#8 mysh0
V tom případě to rozpasuj na jednotlivý slova jak jsem psal výše přes strok(..) a ty potom porovnej

Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
mysh00
Duch
6. 5. 2012   #10
-
0
-

A nedá sa to jednoduchšie pomocou vyššie spomínanej funkcie strstr porovnať, či nie je (hľadaný) reťazec načítaný v hlad podmnožinou reťazca s, ktorý tvorí aktuálne načítaný riadok súboru?

// Tuto som napríklad našiel vzorový príklad, avšak zatiaľ sa mi ho nepodarilo aplikovať na môj prípad.

/* priklad pr7_1.c vyhľadanie podreťazca */
#include <stdio.h>
#include <string.h>

void main(void)
{
  char *s1 = "Text v ktorom hladame vzor";
  char *s2 = "vzor", *pom;

  pom = strstr(s1, s2);
  if (pom != NULL)
    printf("Podretazec %s najdeny v %s na pozicii %d\n", pom,s1,pom - s1);
  else
    printf("Podretazec %s sa v %s nenachdza\n",pom,s1);
}
Nahlásit jako SPAM
IP: 88.212.40.–
ingiraxo+15
Grafoman
6. 5. 2012   #11
-
0
-

#10 mysh0
za určitých okolností by to šlo taky, ale tady je problém ten, že ono to neví, jestli se jedná o slovo nebo část slova... pokud by slovo bylo třeba "automat" a hledal by si slovo "auto", tak ti najde "automat", resp. ti ukáže ptr na znak "a", protože to nerozezná slovo od jeho části

Spíš to udělej jak jsem psal.. pokud v řádku máš oddělený slova něčím, tak to napřed rozparsuj a až potom hledej

Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
mysh00
Duch
6. 5. 2012   #12
-
0
-

Ale principiálne musím stále spraviť to isté - porovnať dva stringy. A to je práve môj problém. Mne stačí len hodnota true alebo false, nepotrebujem žiadne ďalšie informácie - ak true, tak vypíšem daný riadok, ak false, tak ho nevypíšem.

Skúsil som to aj pomocou strtok, ale tiež sa minulo účinku:

  while(fgets( s, sizeof(s), f) != NULL){
  
  char s[4096];
  char delims[] = "; ";
  char *result = NULL;
  result = strtok( s, delims );
  x=strcmp(result,hlad);
  while( result != NULL ) {
      //printf( "Vysledok je \"%s\"\n", result );
       if (x==0) printf("%s",s); 
Nahlásit jako SPAM
IP: 88.212.40.–
ingiraxo+15
Grafoman
6. 5. 2012   #13
-
0
-

Spíš si to napsal špatně.. strtok vrací ukazatel na první nález (chová se to jako lineární seznam), takže to musíš opět posunout na další nález.. a delim je jeden znak, pokud dáš 2 (středník a mezeru), tak to bude hledat  všechno, kde je mezera a středník na sobě nezávislý

Spíš si přečti man k těmto funkcím a napiš aspoň pro vizuální představu pár řádků toho souboru

Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
mysh00
Duch
6. 5. 2012   #14
-
0
-

Záznamy v súbore vyzerajú nejak takto:

1. TUKE; kosice; 12; 2500;
2. UPJS; kosice; 9; 1300;
3. UMB; bystrica; 8; 2000;
4. UK; bratislava; 14; 4000;

Nahlásit jako SPAM
IP: 88.212.40.–
ingiraxo+15
Grafoman
6. 5. 2012   #15
-
0
-

tak pokud to je takto, tak to rozděl podle středníku (dostaneš jednotlivý slova) a budu předpokládat, že porovnáváš název města (char2), takže to může vypadat nějak takto:

char* parse = 0;
parse = strtok(radek, ";");
parse = strtok(0, ";"); // dostanu se na dalsi slovo (mesto)
parse = strstr(parse, "coHledam");

if (parse)
{
    // nasel jsem
}
Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
Řešení
mysh00
Duch
6. 5. 2012   #16
-
0
-
Vyřešeno Nejlepší odpověď

Netuším, kde som robil chybu, ale aktuálne tento kód funguje presne tak, ako som si to predstavoval.

if (volba==3){
 system("clear");
 fr=fopen("subor.txt","r");
 char hlad[15];
 
 int c,x,str,znaky=0;
 printf("VYHLADANIE ZAZNAMU:\n\n");
 printf("Zadajte vyhladavane kriterium: "); 
  scanf("%s",&hlad);
 printf("\n");
 pz=pocetzaznamov();
 znaky=0;
 
 for (i=1;i<=pz;i++){
  while ((c=getc(fr))!='\n') znaky++;   
  printf("V %d. riadku je %d znakov.\n",i,znaky-1);
  znaky=0;
   }
 
 FILE* f;
 
 
  printf("\n\nHladany vyraz sa vyskytuje v nasledujucich zaznamoch: \n \n"); 
  char s[4096];
 
  f=fopen("subor.txt","r");

while(fgets( s, sizeof(s), f) != NULL){
    
     if ((strstr(s,hlad))!=0) puts(s); }

   fclose(f);
          
 
   getchar();
 
}

Týmto považujem problém za uzavretý a ďakujem všetkým zúčastneným za ochotu a pomoc, vážim si to.

Nahlásit jako SPAM
IP: 88.212.40.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 51 hostů

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032016 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý