LINUX.ORG.RU

C reverse strings


0

0

в C не шарю , так что за код не пинайте .
надо сделать следуюшее 

есть строка вида abc.defg надо ее вывести в виде defg.abc
вот во что вылились мои мучения :

#include <stdio.h>
#include <string.h>

int main ()
{
        char    str[255];
        char*   array[255];
        char*   block[255];
        char*   *ps=block;
        int sz,bs,i,j,k=0;
        scanf("%s",str);
        sz = strlen (str);
        j = 0;
        printf("string = %s\n",str);
        for (i = 0 ; i<=sz ; i++) {
                if (str[i] == '.') {
                        j++;
                        i++;
                }
                block[j][i] = str[i];
        }
        for (k=j ; k>=0; k--) {
                array[k] = ps[k];
        }

        for (i = j ; i >=0 ; i-- ) {
                printf("%s.",array[i]);
        }
        //printf("array=%d",bs);

}

в итоге после запуска выводит подобную хрень 

./dot
abc.defg
string = abc.defg
Õ­ù·defg.abc.

откуда берутся начальные символы Õ­ù·??
и что я делаю не правильно ?
★★

"Чем лечить этого, проще родить нового."

#include <stdio.h>
#include <string.h>

int main ()
{
        char    str[255];
	char	out[255];
        int	sz,i,j;
	char * pos;
        scanf("%s",str); //на совести автора
        sz = strlen (str);
		pos=strchr(str,'.');
		if (pos==NULL) 
		{
			strncpy(out,str,254);
		}
		else
		{
			for (i=pos-str+1;i<sz;i++)
				out[j++]=str[i];
			out[j++]='.';
			for (i=0;i<pos-str;i++)
				out[j++]=str[i];
			out[j++]=0;
		}
        printf("string = %s\n",str);
        printf("out = %s\n",out);
}

Ну это, если я правильно понял задачу.

Davidov ★★★★
()
Ответ на: комментарий от j262

> Segmentation fault

Бугага. Си - без вопросов лучший инструмент для подобных задачь.

In [6]: '.'.join(reversed('defg.abc'.split('.')))
Out[6]: 'abc.defg'

anonymous
()

void apply(char *str)
{
  char *ptr;
  char buf;

  while ((ptr = strrchr (str, '.')))
  {
    memmove (ptr, ptr + 1, strlen (ptr + 1));
    str[strlen(str+1)] = '.';
    while (*ptr++)
    {
      buf = str[strlen(str+1)];
      memmove (str + 1, str, strlen (str + 1));
      str[0] = buf;
    }
    if ((str = strchr (str, '.')))
      str++;
  }
}

kmeaw ★★★
()
Ответ на: комментарий от anonymous

неважно , lisp( никогда не видел) или perl , меня интересует почему block[0] нормально выводит , а block[1] уже с левыми символами .

j262 ★★
() автор топика
Ответ на: комментарий от Davidov

#include <stdio.h>
#include <string.h>

int main ()
{
        char    str[255];
		char	out[255];
        int	sz,i,j;
		char * pos;
        scanf("%s",str); //на совести автора
        sz = strlen (str);
		pos=strchr(str,'.');
		if (pos==NULL) 
		{
			strncpy(out,str,254);
		}
		else
		{
			j=0;
			for (i=pos-str+1;i<sz;i++)
				out[j++]=str[i];
			out[j++]='.';
			for (i=0;i<pos-str;i++)
				out[j++]=str[i];
			out[j++]=0;
		}
        printf("string = %s\n",str);
        printf("out = %s\n",out);


}

Davidov ★★★★
()
Ответ на: комментарий от j262

> неважно , lisp( никогда не видел) или perl

А вы корову уже подоили, прежде чем за компилятор браться?

anonymous
()
Ответ на: комментарий от Davidov

ясно, tnx , попробую по другому .

j262 ★★
() автор топика
Ответ на: комментарий от j262

Что вы хотели этим сказать "block[j][i] = str[i];"?

block[j] у вас не инициализирован.

На моей системе предсказуемо выдаёт segmentation fault.

Рекомендую valgrind.

Davidov ★★★★
()
Ответ на: комментарий от Davidov

идея была записывать в некоторый массив символы , пока не дойдет до '.' 
потом этот содержимое этого массива block[j] передавать в array
при этом хотелось чтобы название block было динамическим 

после этого в array по идее должно было оставаться 2 элемента abc,defg

кстати я проверил на другой машине в segfault не выпадает . но полюбому как-то криво вышло , ваш код я более менее понял , но хочу сделать по другому .

посмотю на функции strings.h 

j262 ★★
() автор топика
Ответ на: комментарий от j262

Не расходуя память впустую:

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

int main () {
		char    str[256];
		int	sz,i,j;
		int cnt; //число точек
		char **ps; //массив указателей на строки
		scanf("%255s",str);
		sz = strlen (str);
		/* посчитаем количество строк */
		cnt=1;
		for (i=0;i<sz;i++)
			if (str[i]=='.')
				cnt++;
		ps=calloc(cnt, sizeof(char *));
		if (ps==NULL) {
			printf("Error allocating memory.\n");
			return 1;
		}
		ps[0]=str;
		i=0;
		for (j=1;j<cnt;j++)	{
			while (str[i]!='.') i++;
			str[i]=0;
			i++;
			ps[j]=str+i;
		}
		for (j=0;j<cnt;j++)
			printf("ps[%d]=%s\n",j,ps[j]);
		for (j=cnt-1;j>=0;j--) {
			printf("%s",ps[j]);
			if (j!=0) printf(".");
		}
		printf("\n");
		return 0;
}


Davidov ★★★★
()
Ответ на: комментарий от Davidov

крута :) , я столько функций пока не знаю .

j262 ★★
() автор топика
Ответ на: комментарий от anonymous

(string-join (reverse (string-split "asd.fghj" ".")) ".")

anonymous
()
Ответ на: комментарий от Davidov

>Не расходуя память впустую: >...

кстати эту задачу можно решить вообще без выделения дополнительной памяти, развернув строку на месте.

rip_someday
()

Если халявить то так (без всяких проверок):

void reverse(char* s) {
    char* buffer = strdup(s), *p =strchr(buffer, '.');
    *p = '\0';
    sprintf(s, "%s.%s", p + 1, buffer);
    free(buffer);
}

anonymous
()
Ответ на: комментарий от rip_someday

#include <stdio.h>
#include <string.h>
char* rev(char* s, char* head) {
    char c = *s, *tgt;

    if (*s == '.')
        return head;

    tgt = rev(s==head?head+strlen(head)-1:s-1, head);
    if (s==head) *(tgt++) = '.';

    *tgt = c;

    return tgt+1;
}

main() {
    char s[255];

    scanf("%s", s);
    rev(strchr(s,'.')-1, s);
    printf("%s\n", s);

    return 0;
}

Murr ★★
()

Обычно условие этой задачи требует не выделять памяти. Я вам обломаю весь кайф: делается это приведенным ниже кодом ;-)

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

void reverse_substr(char *str, int len) {
    int i;
    for(i=0; i<len/2; ++i) {
        char tmp;
        tmp = str[i];
        str[i] = str[len-i-1];
        str[len-i-1] = tmp;
    }
}

int main(int argv, char **argc) {
    if (argv < 2) {
        puts("Argument required");
        exit(1);
    }
    char *line = argc[1];
    char *start, *end;
    reverse_substr(line, strlen(line));
    start = end = line;
    do {
        if(*end == '.' || *end == 0) {
            reverse_substr(start, end-start);
            start = end+1;
        }
    } while(*end++);
    puts(line);
}
==== cut ====

$ ./reverse foo.bar.baz
baz.bar.foo

anonymous
()
Ответ на: комментарий от anonymous

 Murr &   anonymous (*) (17.07.2007 19:19:52) respect 


написаное anonymous (*) (17.07.2007 19:19:52)  больше всего понравилось.

j262 ★★
() автор топика
Ответ на: комментарий от anonymous

можно еще так , без дополнительной переменной tmp.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void reverse_substr(char *str, int len) {
    int i;
    for(i=0; i<len/2; ++i) {
        str[i] = str[len-i-1] - str[i];
        str[len-i-1] = str[len-i-1] - str[i];
        str[i] = str[len-i-1] + str[i];
    }
}

int main(int argv, char **argc) {
    if (argv < 2) {
        puts("Argument required");
        exit(1);
    }
    char *line = argc[1];
    char *start, *end;
    reverse_substr(line, strlen(line));
    start = end = line;
    do {
        if(*end == '.' || *end == 0) {
            reverse_substr(start, end-start);
            start = end+1;
        }
    } while(*end++);
    puts(line);
}

j262 ★★
() автор топика

#include <stdio.h>
#include <string.h>
#define BUF_SIZE 4096
char buf[BUF_SIZE];
int reverse_print(char *str,char *delimiters) {
   int len;
   str+=strspn(str,delimiters);
   if (str[0]==0 || str[0]=='\n')
      return 0;
   len=strcspn(str,delimiters);
   if (len!=0 && reverse_print(str+len,delimiters))
         putchar(delimiters[0]);
   fwrite(str,1,len,stdout);
   return 1;
}
int main() {
   char *str;
   str=fgets(buf,BUF_SIZE-1,stdin);
   if (str==NULL || str[0]==0 || str[0]=='\n')
      exit(1);
   reverse_print(str,". \t\v\n");
}
/** просто к слову пришлось..
нафига там всякие лишние массивы,
если буфер сильно конечный то рекурсия рулит */

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

Гм. Зачем так извращаться, если  только распечатывать в обратном порядке.

#include <string.h>
#include <stdio.h>

int main(void) {
    char s[256], *p = strchr(strcpy(s, "abc.defg"), '.');
    *p = '\0';
    printf("%s.%s\n", p + 1, s);
    return 0;
}

anonymous
()
Ответ на: комментарий от MKuznetsov

Если не два, можно так.
#include <string.h>
#include <stdio.h>

int main(void) {
	char s[256];
	char *p;
	strcpy(s, "my.name.is.Yoda.Minch");
	while ( (p=strrchr(s,'.')) != NULL) {
		*p=0;
		printf("%s.", p+1);
	}
	printf("%s\n", s);
	return 0;
}

или с меньшим количеством проходов и без изменения массива.
(хотя код несколько странный)

#include <string.h>
#include <stdio.h>

int main(void) {
	char *s="my.name.is.Yoda.Minch";
	int i,j;
	for (i=strlen(s)-1;i>=-1;i--)
		if (i==-1||s[i]=='.') {
			for (j=i+1;s[j]!='.'&&s[j]!=0;j++)
				putchar(s[j]);
			if (i!=-1) putchar('.');
		}
	putchar('\n');
	return 0;
}

По-моему, так. (C)

Davidov ★★★★
()
Ответ на: комментарий от j262

Спасибо :)

Единственная тонкость: "if (i==-1||s[i]=='.')". Должно быть записано
именно в таком порядке, потому что иначе будет обращение к -1 элементу
массива (т.е. выход за границы выделенной памяти). Ошибки нет, но стиль не самый хороший.

Наверное, так будет правильнее:
#include <string.h>
#include <stdio.h>

#define SEP '.'

void print_until_dot(char *s) {
	int i;
	for (i=0;s[i]!=SEP&&s[i]!=0;i++)
		putchar(s[i]);
}

int main(void) {
	char *s="my.name.is.Yoda.Minch";
	int i;
	for (i=strlen(s)-1;i>=0;i--)
		if (s[i]==SEP) {
			print_until_dot(s+i+1);
			putchar(SEP);
		}
	print_until_dot(s);
	putchar('\n');
	return 0;
}

P.S. И всё же в высокоуровневых языках есть своя прелесть.

Python 2.5.1 (r251:54863, May  2 2007, 16:56:35) 
[GCC 4.1.2 (Ubuntu 4.1.2-0ubuntu4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> a="my.name.is.Yoda.Minch"
>>> b=a.split('.')
>>> b.reverse()
>>> '.'.join(b)
'Minch.Yoda.is.name.my'

Хотя да, у Руби получается по-короче (почему-то reverse в питоне ничего не возвращает).

Davidov ★★★★
()
21 августа 2007 г.
Ответ на: комментарий от anonymous

вот простой код на Си++

#include <iostream> #include <string>

using namespace std;

void main() { string s; cin >> s; string::reverse_iterator ii = s.rbegin(); string res;

for(int n = 0, last = -1; ii != s.rend(); ++ii, ++n) { if(*ii == '.') { res += s.substr(s.size() - n, n - last - 1) + '.'; /*cout << s.substr(s.size() - n, n - last - 1) + '.';*/ last = n; } if(ii + 1 == s.rend() ) res += s.substr(0, s.size() - last - 1); }

cout << res << endl; }

anonymous
()
Ответ на: комментарий от anonymous

#include <iostream>
#include <string>

using namespace std;

void main()
{
string s;
cin >> s;
string::reverse_iterator ii = s.rbegin();
string res;

for(int n = 0, last = -1; ii != s.rend(); ++ii, ++n)
{
if(*ii == '.')
{
res += s.substr(s.size() - n, n - last - 1) + '.'; /*cout << s.substr(s.size() - n, n - last - 1) + '.';*/
last = n;
}
if(ii + 1 == s.rend() ) res += s.substr(0, s.size() - last - 1);
}


cout << res << endl;
}

anonymous
()
Ответ на: комментарий от anonymous

#include <iostream> #include <string>

using namespace std;

void main() { string s; cin >> s; string::reverse_iterator ii = s.rbegin(); string res;

for(int n = 0, last = -1; ii != s.rend(); ++ii, ++n) { if(*ii == '.') { res += s.substr(s.size() - n, n - last - 1) + '.'; /*cout << s.substr(s.size() - n, n - last - 1) + '.';*/ last = n; } if(ii + 1 == s.rend() ) res += s.substr(0, s.size() - last - 1); }

cout << res << endl; }

anonymous
()
Ответ на: комментарий от anonymous

#include <iostream>
#include <string>

using namespace std;

void main()
{
	string s;
	cin >> s;
	string::reverse_iterator ii = s.rbegin();
	string res;

	for(int n = 0, last = -1; ii != s.rend(); ++ii, ++n)
	{
		if(*ii == '.') 
		{
			res += s.substr(s.size() - n, n - last - 1) + '.'; /*cout << s.substr(s.size() - n, n - last - 1) + '.';*/
			last = n;
		}
		if(ii + 1 == s.rend() ) res += s.substr(0, s.size() - last - 1);
	}
	

	cout << res << endl;
}

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.