Форум: Форум C++Разное
Новые темы: 00
Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум C++

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: c++ Строки
 
 автор: M@M@Z0GL0   (16.12.2008 в 22:10)   письмо автору
 
 

Люди помогите балбесу, 2 неделю пишу программу со строками. Условие задачи следующее
Дана строка, состоящая из групп нулей и единиц. Каждая группа отделяется друг от друга одним или несколькими пробелами.
Вывести на экран первые символы строки, равные количеству символов самой длинной группы.
Help me please.

  Ответить  
 
 автор: exp   (17.12.2008 в 03:33)   письмо автору
 
   для: M@M@Z0GL0   (16.12.2008 в 22:10)
 

какими функциями пытались делать ?

тоже чевойто со строками не разберусь никак , только стандартными сишными функциями хотел
, без strlen(), но почемуто у меня sizeof() всегда показывает 4 со строками, а читал где-то что должен размер строки показывать. Надо попробовать другим компилятором,
#include <stdio.h> // sscanf() printf()
#include <conio.h> // getch();
#include <malloc.h> // calloc() free()
#include <string.h> // strlen()

main() {
  char *str = "111111 000000 11 111111111  00 111";
  char *bf;
  int p=0;
  
if( (bf = (char *)calloc(512, sizeof(char))) == NULL)
   return 1; // выделение памяти или return

char  *gc = (char *)calloc(1, sizeof(char));

while (sscanf( &str[p], "%s*", bf)
       && (p += strlen(bf)) < strlen(str)) {
  while (sscanf(&str[p+1], "%c", gc)
      && gc == " ") { p++; } // здесь баг
/* хотел применить getc() вместо второго sscanf()
    но просто отказалось работать. */

  printf("%s\n %i\n", bf, p);
}

free(gc);
free(bf); // освободить память
  getch();
  return 0;
}

У меня такой вопрос , извиняюсь что в не своей теме ,)
функция getc() обычно работает с указателем на память ?
, как пытался сделать getc(&bf[1])
и почему второй sscanf() не хочет считать пробелы ?
вроде должен считать , если "%c" (пробовал "%Fc", "%Nc", не работает на DevCpp)

  Ответить  
 
 автор: GeorgeIV   (17.12.2008 в 09:25)   письмо автору
 
   для: exp   (17.12.2008 в 03:33)
 

но почемуто у меня sizeof() всегда показывает 4 со строками, а читал где-то что должен
 размер строки показывать. Надо попробовать другим компилятором,

Дело не в компиляторе, а в понимании.
sizeof(str) выдает размер указателя на строку, а он чаще всего будет 4 байта
а sizeof str должен как раз выдать длину строки.


MSDN:
Yields the size of its operand with respect to the size of type char.

 
sizeof unary-expression
sizeof ( type-name )
 

Remarks
The result of the sizeof operator is of type size_t, an integral type defined in the include file
 STDDEF.H. This operator allows you to avoid specifying machine-dependent data sizes in your
 programs.

The operand to sizeof can be one of the following: 

A type name. To use sizeof with a type name, the name must be enclosed in parentheses.

An expression. When used with an expression, sizeof can be specified with or without the
 parentheses. The expression is not evaluated.

  Ответить  
 
 автор: EXP   (17.12.2008 в 18:07)   письмо автору
 
   для: GeorgeIV   (17.12.2008 в 09:25)
 

у меня выдаёт длинну строки только если строка объявлена как char str[37]
, а c указателем даже на такие-же char не смог придумать как посчитать строку

попробовал по другому решить предложенную задачку, но не смог избавиться от strlen()
#include <stdio.h> 
#include <conio.h> 
#include <string.h> // strlen

int main() {
 
int t, i,i2, l2s, max=0;
static char str[37] = "1111   000000 11 111111111  00 111";
char bf[512];

printf("\n sizeof %i\n\n"sizeof str);

for(i=0; 1; i = i2) {

ifsscanf(&str[i], "%s", &bf)< 0) break;
//sscanf не захватывает пробельные символы

l2s = strlen(bf);//
if (max<l2s) max = l2s;

  for(i2=i+l2s; 1; i2++){ // пропуск пробелов 0x20=" "
    if (str[i2] != 0x20) break;
  }
  
  printf(" bf = %s\n", bf);
} // end of for

printf("\n max = %i\n\n\n", max);

i=-1;

while((i+=1) < max) printf("%c", str[i]); // вывод max символов строки

  getch();
  return 0;
}

Не уверен в правильности и оптимальности написания

  Ответить  
 
 автор: bronenos   (17.12.2008 в 19:53)   письмо автору
 
   для: EXP   (17.12.2008 в 18:07)
 

Мельком посмотрел

  for(i2=i+l2s; 1; i2++){ // пропуск пробелов 0x20=" "
    if (str[i2] != 0x20) break;
  }


Можно заменить на

for (i2=i+l2s; str[i2]==0x20; i2++);

  Ответить  
 
 автор: M@M@Z0GL0   (17.12.2008 в 22:25)   письмо автору
 
   для: exp   (17.12.2008 в 03:33)
 

exp
Не знаю как тебя благодарить. Спасибо тебе огромное, единственное что я заменил, это ручной ввод строки и
sizeof на i=strlen (str).
Спасибо еще раз.

  Ответить  
 
 автор: exp   (18.12.2008 в 11:43)   письмо автору
 
   для: M@M@Z0GL0   (17.12.2008 в 22:25)
 

я и сам тут пробую разобраться ,) можно заменить strlen() на свою strlen() такую как дальше в коде

попробовал теперь пересобрать проект как с++
и опять не пойму почему не все переменные адекватно перемениваются .)
#include <stdio.h>
#include <conio.h> // detch()

int strlen(char *s) {
 int y = 0;
 while(s[y] != 0) y++;
 return y;
}

typedef struct xstr{
  char *v;
  int size;
  int count;

  xstr(int sz, char * str) {
 v = new char[size=sz]; // выделение памяти
 count = strlen(str);
  }
   ~xstr() { delete v; }
} xstr;


typedef struct ystr{
  char *v;
  int size;
  int count;
  
   ystr(int sz) { v = new char[size=sz]; // выделение памяти
  count = 0;
}
   ~ystr() { delete v; }
} ystr;



int main() {

ystr ybf(512);
ybf.v = "1234567890 1234567890";

printf("\n ybf.count %i\n ybf.size %i\n strlen %i\n\n"
, ybf.count, ybf.size, strlen(ybf.v));

xstr bf(512, ybf.v);

printf("\n bf.count %i\n bf.size %i\n strlen %i\n\n"
, bf.count, bf.size, strlen( bf.v ));


getch();
  return 0;
}

Никак не соображу почему с объектом bf strlen( bf.v ) возвращает как-будто размер обьекта а не строки

и как-нибудь можно-ли оптимально сделать так чтобы при создании объекта не надо было-бы указывать сколько памяти выделять, а автоматически выделялось-бы,
и как добавить метод strlen() или переопределить какой-нибудь оператор, чтобы возвращало размер строки ?

  Ответить  
 
 автор: GeorgeIV   (18.12.2008 в 16:46)   письмо автору
 
   для: exp   (18.12.2008 в 11:43)
 

вообще то полагается используя массивное new[] использовать массивное delete[] для удаления объекта
После инициализации есть только присвоение одного указателя другому, а автоматического пересчета в структуре естественно не будет
Еще одно замечание - память выделена, но не проинициализирована, завершающего нуля нет, поэтому длина считается до первого попавшегося нуля в памяти после структуры. И с удалением не совсем понятно, они же создаются на стеке и применение оператора delete , по крайней мере в Студии 2008 вызывает ошибку

PS Вобщем программа ведет себя согласно написанному коду.

  Ответить  
 
 автор: GeorgeIV   (18.12.2008 в 17:17)   письмо автору
 
   для: GeorgeIV   (18.12.2008 в 16:46)
 

Небольшие вариации:
//  for(i2=i+l2s; 1; i2++){ // пропуск пробелов 0x20=" "
//    if (str[i2] != 0x20) break;
//  }
  while(str[i2=i+l2s++] == ' ');

//i=-1;

//while((i+=1) < max) printf("%c", str[i]); // вывод max символов строки
str[max] = 0;
printf("%s", str);

  Ответить  
 
 автор: exp   (18.12.2008 в 21:28)   письмо автору
 
   для: GeorgeIV   (18.12.2008 в 17:17)
 

по условиям , если я правильно понял надо что-то вроде
printf("%.9s", str);
но для этого сначала пришлось-бы сгенерировать такую строку формата в зависимости от того сколько символов.
А функциями типа putch() выводить не решился,) на случай возможности отказаться от <conio.h>
, в которой вроде-бы по старой старой документации должна быть функция cscanf(), которую почемуто у меня нет , но есть например _cscanf("%s", bf); , которая совсем очень странно себя ведёт :)
и много других отсутствующих функций находится , если добавить '_'
, неверное это какие-то фичиасмомакросы devcpp :) но приятно иногда использовать _beep(...) вместо putch(7) ;)
насчёт стека думаю это та память которая встроена в сам процессор,
вообще не очень понимаю отличается-ли то где будет размещено содержимое переменной
взависимости от того просто-ли её объявили как char var[123] или использовали var = new char[123],
думаю только что те строки что написаны в коде программы и не изменяются наверное лучше как
static char *str='123'
а со всеми другими уже какие-то сложности, и иногда не похоже что например f(* link) применяет f к самому объекту на который указывает link, а f(&obj) делает что-то с указателем на obj.
Буду пробовать начинать читать всё внимательнее.
Спасибо ;)

  Ответить  
 
 автор: exp   (18.12.2008 в 23:40)   письмо автору
 
   для: exp   (18.12.2008 в 21:28)
 

интересно таки работает это _cscanf()
можно не записывая никаких пробелов получить чистые данные из ввода с командной строки
и создать массив индексов подстрок, посчитать длинну ,и всё это ещё во время только печатания

но не работает :)
int u = i=0;
int len, keys[55]; // длинна строки и адреса подстрок

while (_cscanf("%s", &bf[i])) {
 len = strlen(bf); // printf("\n%.s  %i\n", bf, (len = strlen(bf)));
  keys[u++] = i;
  i = len;
  if (getch() == 0x0d) break// "\n"
}
printf("\n string = %s\n\n", bf);
printf(" keys = \n");
u = 0;

while(keys[u]< sizeof bf) {
 printf(" %i\n", keys[u]);
 u++;
}
getch();
не хочет срабатывать как нужно if (getch() == 0x0d) break; // "\n"
0x0a // "\r" тоже пробовал ;)
если перед нажатием enter есть пробелы ничего не происходит,
:)

  Ответить  
 
 автор: GeorgeIV   (19.12.2008 в 10:03)   письмо автору
 
   для: exp   (18.12.2008 в 21:28)
 

насчёт стека думаю это та память которая встроена в сам процессор,
вообще не очень понимаю отличается-ли то где будет размещено содержимое переменной
взависимости от того просто-ли её объявили как char var[123] или использовали var = new char[123],
думаю только что те строки что написаны в коде программы и не изменяются наверное лучше как
static char *str='123'
Этот кусок показывает, что у вас еще каша в голове по сям.
Если очень упрощенно, стэк принадлежит только данной программе и разрушается вместе с ней. Созданное на стеке самому уничтожать не надо. Так создаются все локальные переменные.
Общая память (куча,heap) принадлежит всем и именно в ней создаются динамические объекты, и то, что вы там создали в сях надо уничтожать самому, иначе возникает утечка памяти.
Варианты с _ появились с введением микрософтом "безопасных" функций, которые позволяют, например, не допустить переполнения буфера. Также существуют функции с _, кторые в зависимости от установок среды работают с типом TCHAR как с char или как с wchar_t.
Если строка не изменяется, и вообще какой то объект, лучше его объявлять как const. Поведение квалификатора static зависит еще от того, в каком месте он использован.
Но это лучше все читать в спецлитературе, MSDN всегда должен быть под рукой, в нем есть все ответы.

  Ответить  
 
 автор: GeorgeIV   (19.12.2008 в 10:13)   письмо автору
 
   для: GeorgeIV   (19.12.2008 в 10:03)
 

Одиночный символ ставится в одинарные кавычки '\r' надоб было использовать. В двойные кавычки заключается строка.
Мне кажется с помощью scanf эту задачу не решить, потому как она не различает все непечатные символы и пока в буфере не будет хоть одного символа , внутрь while прога не войдет.

  Ответить  
 
 автор: exp   (19.12.2008 в 12:06)   письмо автору
 
   для: GeorgeIV   (19.12.2008 в 10:13)
 

MSDN для меня это ещё хуже чем Perldoc в Perl :)
английский пока понимаю слово через четыре , ито если про програмирование пишут :)

Спасибо

  Ответить  
 
 автор: GeorgeIV   (19.12.2008 в 13:21)   письмо автору
 
   для: exp   (19.12.2008 в 12:06)
 

А что делать! Без английского в программировании беда. Сам изучаю его только ради понимания тех.документации

  Ответить  
 
 автор: bronenos   (20.12.2008 в 17:58)   письмо автору
 
   для: exp   (18.12.2008 в 11:43)
 

   ~ystr() { delete v; }

а может
   ~ystr() { delete[] v; }

  Ответить  
 
 автор: WveB   (20.12.2008 в 17:36)   письмо автору
 
   для: exp   (17.12.2008 в 03:33)
 

не будишь-ли ты так любезен и мне помочь в моей задачке ?

  Ответить  
 
 автор: WveB   (20.12.2008 в 15:25)   письмо автору
 
   для: M@M@Z0GL0   (16.12.2008 в 22:10)
 

Уважаемые гении С++ не один M@M@Z0GL0 такой, у меня задание из этой же оперы !
Ему я вижу помогли ! Если Вам не трудно помогите и мне, никак сам сделать не могу, одни ошибки и ничего не работает !
Мое задание:
Дана строка, состоящая из групп нулей и единиц. Каждая группа отделяется друг от друга одним или несколькими пробелами.
Подсчитать количество единиц в самой короткой группе !
Заранее ОГРОМНЕЙШЕЕ СПАСИБО !

  Ответить  
 
 автор: exp   (20.12.2008 в 19:15)   письмо автору
 
   для: WveB   (20.12.2008 в 15:25)
 

зачем обзываться гениями C++ ? :)
каким компилятором пробовали ? ругаются-ли на какой-нибудь код из этой темы, или на что ругается?
компилируется-ли например этот код слегка похожий на задачку ?

#include <conio.h> 

int main() {
char bf[512], x;
int i, cur, last;

cur = last=0;
i = -1;
  _cputs("string & enter: \n\n");
while ((x = getch()) != 0x0d) { // 0x0d == "\n"
 bf[(i+=1)] = x;
 
 if (x == '1')  cur++; // 0x31 == 1
 else if (cur) {
   if (!last || last > cur) last= cur;
   cur = 0;
 }
 putch(x);
}

if (cur && last > cur) last= cur;
bf[(i+=1)] = 0x00; //&#234;îíåö ñòðîêè

_cputs("\nminimum -- ");
_cprintf("%i", last);
_cputs(" characters\nstring -- ");
_cputs(bf);

getch();
  return 0;
}

но только это не c++, это с

  Ответить  
 
 автор: WveB   (20.12.2008 в 19:31)   письмо автору
 
   для: exp   (20.12.2008 в 19:15)
 

А на с++ как сделать ?
Заочникам тяжеловато самим осваивать... тем более если никогда раньше с С++ не общался !
Можешь помочь ?

  Ответить  
 
 автор: exp   (20.12.2008 в 20:08)   письмо автору
 
   для: WveB   (20.12.2008 в 19:31)
 

Я и сам только только начал пытаться понять ;) вот из книги
C++ - универсальный язык программирования, задуманный так, чтобы сделать программирование более приятным для серьезного программиста. За исключением второстепенных деталей C++ является надмножеством языка программирования C. Помимо возможностей, которые дает C, C++ предоставляет гибкие и эффективные средства определения новых типов.

И далее там что-то о классах и структурах и ... OOP вобщем , пока лично заметил только отличия в синтаксисе написания struct в С и struct в С++, компилятор C не понимал то что для C++.
И много примеров на английском , с использованием классов для упрощения работы со строкой , и всяких модулей типа MFC . Вроде обьясняют что как-то разумнее используется памть в этих классах.

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

но то что работает в C должно всётаки работать в C++, другое дело требуется-ли от вас объектно-ориентированный подход к решению задачи

  Ответить  
 
 автор: WveB   (20.12.2008 в 20:37)   письмо автору
 
   для: exp   (20.12.2008 в 20:08)
 

проще говоря ты не знаешь как это сделать ?
Как же ты тогда предъидущюю задачу сделал, которую M@M@ZOGLO не мог сделать ?

  Ответить  
 
 автор: exp   (20.12.2008 в 21:27)   письмо автору
14.1 Кб
 
   для: WveB   (20.12.2008 в 20:37)
 

Вы компилировали и запускали этот последний код ?
(прикрепил exe-файл)
тогда вы должны понять что я ничего не понял из задачки :)

то что группы цифр разделены пробелом , я понял
но посчитать колличество едениц можно и в такой строке 000 111 00 11
можно в такой 0101 1010 1100 100
поэтому я просто считал подряд-идущие еденицы не обращая внимания на любой другой ввод с консоли,
хотя там и правда нет действий над строкой как над массивом
А в предыдущей задачке оказалось что использовалась ещё и строка введённая с консоли
и та задачка решилась совершенно случайно и самопроизвольно тоже на чистом C,пока я решал свои задачки . Я и не знал , что такое решение могло пригодиться вообще :)
Могу сделать на C используя прогон статической строки в цикле, но опять-же 0000 111 или 0101 110 ?
и OOP пока не трогаю , потомучто не знаю

  Ответить  
 
 автор: WveB   (20.12.2008 в 21:31)   письмо автору
 
   для: exp   (20.12.2008 в 21:27)
 

строка идет произвольная, то есть 010110 01101110 110 000 11001
как-то так !
Надо чтоб находилась самая короткая группа и в ней надо посчитать сколько единиц в ней !

  Ответить  
 
 автор: exp   (21.12.2008 в 00:31)   письмо автору
1.4 Кб
 
   для: WveB   (20.12.2008 в 21:31)
 

попробовал тут сделать что-то похожее на C++

и не смог найти как-же при помощи cin получить строку вместе с пробелами :)
вроде всё правильно должно считать с локальной строкой , но почему при вводе новой строки не помещает текст после пробелов?
подскажите есть-ли возможность с помощью cin ввести строку полностью ?
разобрался вроде



здесь есть баг если всего одна группа и ограничения 512

//upd:
прикрепил этот старый код

  Ответить  
 
 автор: WveB   (21.12.2008 в 01:53)   письмо автору
 
   для: exp   (21.12.2008 в 00:31)
 

спасибо что не отказал, но на С++ не работает это, надо компилировать !

  Ответить  
 
 автор: exp   (21.12.2008 в 03:43)   письмо автору
 
   для: WveB   (21.12.2008 в 01:53)
 

вот такой вариант вроде получше
#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
char str[512] = "01110001 1110110 0000001110000 0100100101\0";
char x;
int i, group=0, a=0, ln=0, ones[2];
/*
ones[2]- первый элемент длинна группы из ln 
второй колличество едениц из a
group - только 0 или 1 или 2
*/

cout << "enter digit:"<< endl;
 cout << " 1 new string"<< endl; 
 cout << " 2 default string:"<< endl;
 cout << " '"<< str <<"'"<< endl; // если лениво вводить строку
 cout << " 0 exit"<< endl;
cin >> i;
cout << endl;

switch(i) {
 case 1:
   cout << "(Notice: only ' ', 1, 0 characters)"
   <<endl<<"enter string:"<< endl;

   cout.flush();
   cin.getline(&x, 1); // лишний cin думаю баг devCpp 
   cin.getline(str,511);
 break;
 case 2:
 break;
 default:
   i = 0;
}// end of switch

if (i) {
 i=0;

for (i=0; (x = str[i]) != 0x00; i++) {

   switch (x) {
   case '1':
     ln++;
     a++;
     group=2;
   break;
   case '0':
     ln++;
     group=2;
   break;
   default:
    if (group>1 && (!ones[0] || ones[0]>ln)) {
       ones[0] = ln;
       ones[1] = a;
     }
  group = (group)? 1: 0;
  ln = a = 0;

 }// end of switch
}// end of while

    if (group>1 && (!ones[0] || ones[0]>ln)) {
       ones[0] = ln;
       ones[1] = a;
     } // последнее возможное нахождение

cout <<endl<<"result: "<< ones[1]<< endl;
cout <<"length group = "<< ones[0]<< endl;
cout <<"string = "<< str << endl;
}
   // system("PAUSE");

cin.getline(&x, 1); // // лишний cin думаю баг devCpp 
cin.getline(&x, 1); // типа getch();
 return 0;
}

какие ошибки выдаёт ?

  Ответить  
 
 автор: WveB   (21.12.2008 в 21:24)   письмо автору
 
   для: exp   (21.12.2008 в 03:43)
 

Ошибки такие :
massiv.CPP(2,16):namespace name expected
massiv.CPP(77,2):Parameter 'argv' is never used
Вот такие вот ошибки

  Ответить  
 
 автор: exp   (21.12.2008 в 21:58)   письмо автору
 
   для: WveB   (21.12.2008 в 21:24)
 

похоже на Borland C++BuilderX
попробуйте просто заменить

int main(int argc, char *argv[])
таким
int main()

просто жаловалось на то что эти переменные не разу не использовались

хотя наверное ещё лучше включить в начале файл
#include <stdlib.h>

и раскомментировать в конце
system("PAUSE");
удалив эти два вызова cin.getline(&x, 1); // // лишний cin думаю баг devCpp
cin.getline(&x, 1); // типа getch()

//PS
два cin.getline оказалось и в C++BuilderX так-же как в devCpp
думаю баг Виндовс :))

  Ответить  
 
 автор: WveB   (21.12.2008 в 22:01)   письмо автору
 
   для: exp   (21.12.2008 в 21:58)
 

ругается вот на эту строчку
namespace std;

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования